Array
ist implementiert mit Copy-on-Write-Verhalten - Sie erhalten es unabhängig von Compiler-Optimierungen (obwohl Optimierungen natürlich die Anzahl der Fälle reduzieren können, in denen eine Kopie benötigt wird geschehen).
Auf einer grundlegenden Ebene ist Array
nur eine Struktur, die einen Verweis auf einen Heap-allokierten Puffer enthält, der die Elemente enthält - daher können mehrere Array
-Instanzen auf den selben -Puffer verweisen. Wenn Sie eine bestimmte Array-Instanz mutieren, überprüft die Implementierung, ob der Puffer eindeutig referenziert ist, und wenn dies der Fall ist, mutieren Sie direkt. Andernfalls führt das Array eine Kopie des zugrunde liegenden Puffers aus, um die Wertesemantik beizubehalten.
Mit Ihrer Point
-Struktur implementieren Sie jedoch nicht das Kopieren beim Schreiben auf Sprachenebene. Natürlich, wie @Alexander sagt dies nicht Stoppen Sie den Compiler nicht, alle Arten von Optimierungen durchzuführen, um die Kosten für das Kopieren ganzer Strukturen zu minimieren. Diese Optimierungen müssen jedoch nicht dem genauen Verhalten von copy-on-write folgen - der Compiler kann einfach was auch immer er wünscht, solange das Programm entsprechend der Sprachspezifikation läuft.
In Ihrem speziellen Beispiel sind sowohl p1
als auch p2
global, daher muss der Compiler sie zu verschiedenen Instanzen machen, da andere .swift-Dateien im selben Modul Zugriff darauf haben (obwohl dies möglicherweise weg optimiert werden könnte) mit Vollmodul-Optimierung). Der Compiler muss die Instanzen jedoch immer noch nicht kopieren - er kann nur das Floating evaluieren. -Punkt-Zusatz zur Kompilierzeit und initialisiere eines der Globals mit 0.0
und das andere mit 1.0
.
Und wenn es sich um lokale Variablen in einer Funktion handelt, zum Beispiel:
%Vor% Der Compiler muss noch nicht einmal zwei Point
-Instanzen erstellen - er kann nur eine einzige lokale Gleitkomma-Variable erstellen, die mit 1.0
initialisiert wurde, und diese ausgeben.
Bezüglich der Übergabe von Werttypen als Funktionsargumente, für ausreichend große Typen und (im Fall von Strukturen) Funktionen, die genügend ihrer Eigenschaften verwenden, ist der Compiler kann sie durch Referenz übergeben und nicht kopieren. Der Angerufene kann dann nur dann eine Kopie von ihnen erstellen, wenn er benötigt wird, etwa wenn er mit einer veränderbaren Kopie arbeiten muss.
In anderen Fällen, in denen Strukturen nach Wert übergeben werden, ist es auch für den Compiler möglich, Funktionen spezialisieren , um nur über die Eigenschaften zu kopieren, die die Funktion benötigt.
Für den folgenden Code:
%Vor% Angenommen, foo(p:)
wird vom Compiler nicht eingebunden (dies wird in diesem Beispiel der Fall sein, aber sobald die Implementierung eine bestimmte Größe erreicht, wird der Compiler es nicht mehr wert finden) - der Compiler kann die Funktion spezialisieren als:
Er übergibt nur den Wert der Eigenschaft Point
von x
an die Funktion und spart damit die Kosten für das Kopieren der Eigenschaft y
.
Der Compiler wird also alles tun, um das Kopieren von Werttypen zu reduzieren. Aber bei so vielen verschiedenen Optimierungen unter verschiedenen Umständen kann man das optimierte Verhalten beliebiger Wertetypen nicht einfach auf Copy-on-Write herunterkochen.
Tags und Links swift copy-on-write value-type