Diese Antwort handelte ursprünglich von den Unterschieden in der Leistung zwischen Strukturen und Klassen. Leider gibt es zu viel Kontroverse um die Methode, die ich zum Messen verwendet habe. Ich habe sie unten gelassen, aber bitte interpretieren Sie sie nicht zu stark. Ich denke, nach all diesen Jahren ist es in der Swift-Community klar geworden, dass Strukturen (zusammen mit Enums) aufgrund ihrer Einfachheit und Sicherheit immer bevorzugt werden.
Wenn die Leistung für Ihre App wichtig ist, messen Sie es selbst. Ich denke immer noch, dass die Leistung von Strukturen in den meisten Fällen überlegen ist, aber die beste Antwort ist genau das, was jemand in den Kommentaren gesagt hat: Es kommt darauf an.
\=== ALTER ANTWORT ===
Da Strukturinstanzen auf dem Stapel allokiert werden und Klasseninstanzen auf dem Heap allokiert werden, können Strukturen manchmal drastisch schneller sein.
Sie sollten jedoch immer selbst messen und basierend auf Ihrem speziellen Anwendungsfall entscheiden.
Betrachten Sie das folgende Beispiel, das 2 Strategien zum Verpacken des Datentyps Int
mit struct
und class
zeigt. Ich verwende 10 wiederholte Werte, um die Realität besser widerzuspiegeln, in der Sie mehrere Felder haben.
class Int10Klasse {
let wert1, wert2, wert3, wert4, wert5, wert6, wert7, wert8, wert9, wert10: Int
init(_ val: Int) {
self.wert1 = val
self.wert2 = val
self.wert3 = val
self.wert4 = val
self.wert5 = val
self.wert6 = val
self.wert7 = val
self.wert8 = val
self.wert9 = val
self.wert10 = val
}
}
struct Int10Struktur {
let wert1, wert2, wert3, wert4, wert5, wert6, wert7, wert8, wert9, wert10: Int
init(_ val: Int) {
self.wert1 = val
self.wert2 = val
self.wert3 = val
self.wert4 = val
self.wert5 = val
self.wert6 = val
self.wert7 = val
self.wert8 = val
self.wert9 = val
self.wert10 = val
}
}
func + (x: Int10Klasse, y: Int10Klasse) -> Int10Klasse {
return Int10Klasse(x.wert + y.wert)
}
func + (x: Int10Struktur, y: Int10Struktur) -> Int10Struktur {
return Int10Struktur(x.wert + y.wert)
}
Die Leistung wird gemessen mit
// Messen von Int10Klasse
messung("klasse (10 Felder)") {
var x = Int10Klasse(0)
for _ in 1...10000000 {
x = x + Int10Klasse(1)
}
}
// Messen von Int10Struktur
messung("struktur (10 Felder)") {
var y = Int10Struktur(0)
for _ in 1...10000000 {
y = y + Int10Struktur(1)
}
}
func messung(name: String, @noescape block: () -> ()) {
let t0 = CACurrentMediaTime()
block()
let dt = CACurrentMediaTime() - t0
print("\(name) -> \(dt)")
}
Der Code befindet sich unter https://github.com/knguyen2708/StructVsClassPerformance
UPDATE (27. März 2018):
Ab Swift 4.0, Xcode 9.2, Ausführung eines Release-Builds auf dem iPhone 6S, iOS 11.2.6, Swift Compiler-Einstellung ist -O -whole-module-optimization
:
- Die
class
-Version dauerte 2,06 Sekunden
- Die
struct
-Version dauerte 4,17e-08 Sekunden (50.000.000 Mal schneller)
(Ich führe nicht mehr Durchschnitte mehrerer Durchläufe durch, da Abweichungen sehr gering sind, unter 5%)
Anmerkung: Der Unterschied ist ohne ganze Moduloptimierung deutlich weniger dramatisch. Ich wäre dankbar, wenn jemand darauf hinweisen könnte, was die Flagge tatsächlich macht.
UPDATE (7. Mai 2016):
Ab Swift 2.2.1, Xcode 7.3, Ausführung eines Release-Builds auf dem iPhone 6S, iOS 9.3.1, im Durchschnitt über 5 Durchläufe, Swift Compiler-Einstellung ist -O -whole-module-optimization
:
- Die
class
-Version dauerte 2,159942142 Sekunden
- Die
struct
-Version dauerte 5,83E-08 Sekunden (37.000.000 Mal schneller)
Anmerkung: Wie jemand erwähnte, dass in realen Szenarien wahrscheinlich mehr als 1 Feld in einer Struktur vorhanden sein wird, habe ich Tests für Strukturen/Klassen mit 10 Feldern anstelle von 1 hinzugefügt. Überraschenderweise variieren die Ergebnisse nicht viel.
URSPRÜNGLICHE ERGEBNISSE (1. Juni 2014):
(Wurde auf Struktur/Klasse mit 1 Feld, nicht 10, ausgeführt)
Ab Swift 1.2, Xcode 6.3.2, Ausführung eines Release-Builds auf dem iPhone 5S, iOS 8.3, im Durchschnitt über 5 Durchläufe
- Die
class
-Version dauerte 9,788332333 Sekunden
- Die
struct
-Version dauerte 0,010532942 Sekunden (900 Mal schneller)
ALTEN ERGEBNISSE (aus unbekannter Zeit)
(Wurde auf Struktur/Klasse mit 1 Feld, nicht 10, ausgeführt)
Bei einem Release-Build auf meinem MacBook Pro:
- Die
class
-Version dauerte 1,10082 Sekunden
- Die
struct
-Version dauerte 0,02324 Sekunden (50 Mal schneller)
13 Stimmen
Strukturen werden immer kopiert, wenn sie in Ihrem Code weitergereicht werden und verwenden kein Referenzzählen. Quelle: developer.apple.com/library/prerelease/ios/documentation/swift/…
4 Stimmen
Ich würde sagen, dass structs besser geeignet sind, um Daten zu speichern, nicht Logik. Um es in Java-Begriffen auszudrücken, stelle dir structs als "Value Objects" vor.
6 Stimmen
Ich bin erstaunt, dass im gesamten Gespräch nicht direkt auf copy-on-write oder lazy copy verwiesen wird. Eventuelle Bedenken in Bezug auf die Leistung beim Strukturkopieren sind aufgrund dieses Designs größtenteils obsolet.
5 Stimmen
Die Wahl einer Struktur über eine Klasse ist keine Frage der Meinung. Es gibt spezifische Gründe, eine davon zu wählen.
1 Stimmen
Ich empfehle dringend, Warum Array nicht threadSafe ist anzusehen. Dies ist relevant, da Arrays & Strukturen beide Werttypen sind. Alle Antworten hier erwähnen, dass mit Strukturen/Arrays/Werttypen niemals ein Thread-Sicherheitsproblem auftreten wird, aber es gibt einen Sonderfall, in dem dies der Fall ist.
0 Stimmen
Apple hat jetzt (ab 2019) einen Artikel, der diese Frage direkt anspricht Auswahl zwischen Strukturen und Klassen.
0 Stimmen
@DavidJames Die Programmiersprache Swift: Strukturen und Klassen: Strukturen und Aufzählungen sind Wertearten sagt: "Sammlungen, die von der Standardbibliothek definiert sind, wie Arrays, Dictionaries und Strings" (nicht alle Strukturen) verwenden die Copy-on-Write-Technik. Siehe Kopiert Swift bei allen Strukturen?
0 Stimmen
Abgesehen von Swift komme ich langsam zu dem Schluss, dass die Verwendung von Java als primäre Unterrichtssprache möglicherweise ein größeres Problem darstellt als ich in den späten 90ern gedacht habe. Vergessen wir Pointer (Arithmetik), es scheint ein vollständiges Verständnis dessen zu fehlen, was ein zusammengesetzter Werttyp ist und warum er wichtig ist. C# hat es sicherlich inkludiert, C und C++ haben es offensichtlich, aber es fehlt sowohl Java als auch seinem JVM, bis die Valhalla-Initiative übernimmt.