Ich bin wirklich neu in Swift und habe gerade gelesen, dass Klassen als Referenz übergeben und Arrays / Strings usw. kopiert werden.
Ist die Referenzübergabe dieselbe wie in Objective-C oder Java, in der Sie tatsächlich eine Referenz übergeben, oder ist sie eine ordnungsgemäße Referenzübergabe?
swift
pass-by-reference
pass-by-value
pass-by-pointer
gran_profaci
quelle
quelle
Antworten:
Arten von Dingen in Swift
Die Regel lautet:
Klasseninstanzen sind Referenztypen (dh Ihre Referenz auf eine Klasseninstanz ist effektiv ein Zeiger )
Funktionen sind Referenztypen
Alles andere ist ein Werttyp ; "alles andere" bedeutet einfach Instanzen von Strukturen und Instanzen von Aufzählungen, denn das ist alles, was es in Swift gibt. Arrays und Strings sind beispielsweise Strukturinstanzen. Sie können einen Verweis auf eines dieser Dinge (als Funktionsargument) übergeben,
inout
indem Sie die Adresse verwenden und verwenden, wie newacct hervorgehoben hat. Der Typ ist jedoch selbst ein Werttyp.Was Referenztypen für Sie bedeuten
Ein Referenztypobjekt ist in der Praxis besonders, weil:
Die bloße Zuweisung oder Übergabe an die Funktion kann zu mehreren Verweisen auf dasselbe Objekt führen
Das Objekt selbst ist veränderbar, selbst wenn der Verweis darauf eine Konstante ist (
let
entweder explizit oder implizit).Eine Mutation des Objekts wirkt sich auf dieses Objekt aus, wie aus allen Verweisen darauf hervorgeht.
Das können Gefahren sein, also pass auf. Andererseits ist das Übergeben eines Referenztyps eindeutig effizient, da nur ein Zeiger kopiert und übergeben wird, was trivial ist.
Welche Werttypen bedeuten für Sie?
Das Übergeben eines Werttyps ist eindeutig "sicherer" und
let
bedeutet, was darin steht: Sie können eine Strukturinstanz oder eine Enum-Instanz nicht über einelet
Referenz mutieren . Andererseits wird diese Sicherheit erreicht, indem eine separate Kopie des Wertes erstellt wird, nicht wahr? Ist das Übergeben eines Werttyps nicht potenziell teuer?Ja und nein. Es ist nicht so schlimm, wie Sie vielleicht denken. Wie Nate Cook gesagt hat, bedeutet das Übergeben eines Werttyps nicht unbedingt das Kopieren, da
let
(explizit oder implizit) Unveränderlichkeit garantiert wird, sodass nichts kopiert werden muss. Und selbst in eine vorübergehendenvar
Referenz bedeutet nicht , dass die Dinge werden kopiert werden, nur , dass sie können , wenn notwendig sein (weil es eine Mutation ist). Die Dokumentation rät Ihnen ausdrücklich, Ihre Schlüpfer nicht in eine Wendung zu bringen.quelle
inout
unabhängig vom Typ ist. Ob etwas als Referenz übergeben wird, ist orthogonal zu Typen.Es wird immer als Wert übergeben, wenn der Parameter nicht vorhanden ist
inout
.Es ist immer eine Referenzübergabe, wenn der Parameter ist
inout
. Dies ist jedoch etwas kompliziert, da Sie das explizit verwenden müssen&
Operator für das Argument wenn Sie an eineninout
Parameter übergeben, sodass er möglicherweise nicht der herkömmlichen Definition von Referenzübergabe entspricht, bei der Sie die Variable direkt übergeben.quelle
inout
)inout
wird eigentlich nicht als Referenz übergeben, sondern als Kopie kopiert. Es wird nur garantiert, dass nach dem Funktionsaufruf dem ursprünglichen Argument ein geänderter Wert zugewiesen wird. In-Out-ParameterAlles in Swift wird standardmäßig als "Kopie" übergeben. Wenn Sie also einen Werttyp übergeben, erhalten Sie eine Kopie des Werts, und wenn Sie einen Referenztyp übergeben, erhalten Sie eine Kopie der Referenz mit allem, was dazu gehört. (Das heißt, die Kopie der Referenz zeigt immer noch auf dieselbe Instanz wie die ursprüngliche Referenz.)
Ich verwende Angstzitate um die "Kopie" oben, weil Swift viel optimiert; Wo immer möglich, wird es erst kopiert, wenn eine Mutation oder die Möglichkeit einer Mutation vorliegt. Da Parameter standardmäßig unveränderlich sind, bedeutet dies, dass die meiste Zeit tatsächlich keine Kopie stattfindet.
quelle
Hier ist ein kleines Codebeispiel zum Übergeben als Referenz. Vermeiden Sie dies, es sei denn, Sie haben einen starken Grund dazu.
Nennen Sie es so
quelle
inout
ist ein Operator zum Kopieren und Kopieren. Es wird zuerst in das Objekt kopiert und dann das ursprüngliche Objekt überschrieben, nachdem die Funktion zurückgekehrt ist. Während es gleich scheinen mag, gibt es subtile Unterschiede.Das Apple Swift Developer- Blog enthält einen Beitrag mit dem Namen " Wert- und Referenztypen" , der eine klare und detaillierte Diskussion zu diesem Thema bietet.
Zitieren:
Der Swift-Blogbeitrag erklärt die Unterschiede weiterhin anhand von Beispielen und schlägt vor, wann Sie sie übereinander verwenden würden.
quelle
Klassen werden von Referenzen übergeben und andere werden standardmäßig als Wert übergeben. Sie können mit dem
inout
Schlüsselwort als Referenz übergeben .quelle
inout
ist ein Operator zum Kopieren und Kopieren. Es wird zuerst in das Objekt kopiert und dann das ursprüngliche Objekt überschrieben, nachdem die Funktion zurückgekehrt ist. Während es gleich scheinen mag, gibt es subtile Unterschiede.Wenn Sie inout mit einem Infix-Operator wie + = verwenden, kann das Symbol & address ignoriert werden. Ich denke, der Compiler geht davon aus, dass er als Referenz übergeben wird.
origDictionary + = newDictionaryToAdd
Und schön, dieses Wörterbuch 'hinzufügen' schreibt auch nur auf die ursprüngliche Referenz, also großartig zum Sperren!
quelle
Klassen und Strukturen
Einer der wichtigsten Unterschiede zwischen Strukturen und Klassen besteht darin, dass Strukturen immer kopiert werden, wenn sie in Ihrem Code herumgereicht werden, Klassen jedoch als Referenz übergeben werden.
Verschlüsse
Wenn Sie einer Eigenschaft einer Klasseninstanz einen Abschluss zuweisen und der Abschluss diese Instanz unter Bezugnahme auf die Instanz oder ihre Mitglieder erfasst, erstellen Sie einen starken Referenzzyklus zwischen dem Abschluss und der Instanz. Swift verwendet Erfassungslisten, um diese starken Referenzzyklen zu unterbrechen
ARC (Automatic Reference Counting)
Die Referenzzählung gilt nur für Instanzen von Klassen. Strukturen und Aufzählungen sind Werttypen, keine Referenztypen und werden nicht gespeichert und als Referenz übergeben.
quelle