Betrachten Sie die folgende C ++ - Methode:
%Vor%Was genau macht der Block, wenn er "Knoten" erfasst? Die Sprachspezifikation für Blöcke Ссылка ist für andere Fälle klar:
Variablen, die im Rahmen der zusammengesetzten Anweisung verwendet werden, sind normal an den Block gebunden, mit Ausnahme derer im automatischen (Stapel-) Speicher. So kann man auf Funktionen und globale Variablen zugreifen, wie man es erwarten würde, ebenso wie auf statische lokale Variablen. [testme]
Lokale automatische (Stapel-) Variablen, auf die in der zusammengesetzten Anweisung eines Blocks verwiesen wird, werden importiert und vom Block als konstante Kopien erfasst.
Aber erfassen wir hier den aktuellen Wert von dies ? Eine Kopie von this mit dem Kopierkonstruktor von Worker? Oder ein Verweis auf den Ort, an dem Knoten gespeichert ist?
Nehmen wir an, wir sagen
%Vor%Das Objekt fred existiert möglicherweise nicht mehr, wenn der Block ausgeführt wird. Was ist der Wert von Knoten ? (Nehmen Sie an, dass die zugrunde liegenden Node-Objekte für immer existieren, aber Workers kommen und gehen.)
Wenn wir stattdessen
geschrieben haben %Vor%ist das Ergebnis anders?
Laut dieser Seite :
Im Allgemeinen können Sie C ++ Objekte innerhalb eines Blocks verwenden. Innerhalb eines Mitglieds Funktion, Verweise auf Membervariablen und Funktionen sind über eine implizit importiert
this
Zeiger und somit veränderlich erscheinen. Es gibt zwei Überlegungen, die gelten, wenn ein Block kopiert wird:
- Wenn Sie eine __block-Speicherklasse für das haben, was a gewesen wäre Stack-basiertes C ++ - Objekt, dann wird der übliche Kopierkonstruktor verwendet.
- Wenn Sie verwenden ein beliebiges anderes C ++ stack-basiertes Objekt innerhalb eines Blocks Habe einen Const-Copy-Konstruktor. Das C ++ - Objekt wird dann mit kopiert dieser Konstruktor.
Empirisch beobachte ich, dass const den this
Zeiger in den Block kopiert. Wenn die C ++ - Instanz, auf die this
zeigt, nicht mehr an dieser Adresse ist, wenn der Block ausgeführt wird (z. B. wenn die Worker-Instanz, auf der Worker::Work()
aufgerufen wird, in einem höheren Frame stack-allokiert wurde), erhalten Sie ein EXC_BAD_ACCESS oder schlechter (z. B. Zeiger-Aliasing). So scheint es:
this
und kopiert Instanzvariablen nicht nach Wert. this
alive zu setzen. Wenn ich auf ein C ++ - Objekt mit lokalem Stack-Zuweisung (dh in diesem Stack-Frame / Scope deklariert) Bezug nehme, beobachte ich, dass sein Copy-Konstruktor aufgerufen wird, wenn es anfänglich vom Block erfasst wird, und dann immer dann, wenn der Block ist kopiert (zum Beispiel durch die Operationswarteschlange, wenn Sie die Operation in die Warteschlange stellen).
Um Ihre Fragen gezielt anzusprechen:
Aber erfassen wir hier den aktuellen Wert von
this
? Eine Kopie davon mit dem Kopierkonstruktor von Worker? Oder eine Referenz auf den Ort, an dem der Knoten gespeichert ist?
Wir erfassen this
. Betrachte es als const-Kopie von intptr_t
wenn das hilft.
Das Objekt
fred
existiert möglicherweise nicht mehr, wenn der Block ausgeführt wird. Was ist der Wert vonnode
? (Nehmen Sie an, dass die zugrunde liegenden Node-Objekte für immer existieren, aber Workers kommen und gehen.)
In diesem Fall wurde this
von-Wert erfasst und node
ist effektiv ein Zeiger mit dem Wert this + <offset of node in Worker>
, aber seit der Worker-Instanz ist es weg, es ist effektiv ein Müll-Zeiger.
Ich würde keine Magie oder anderes Verhalten als genau das, was in diesen Dokumenten beschrieben ist, ableiten.
Wenn Sie in C ++ eine Instanzvariable node
schreiben, ohne explizit something->node
zu schreiben, ist dies implizit this->node
. (Ähnlich wie in Objective-C, wenn Sie eine Instanzvariable node
schreiben, ohne explizit something->node
zu schreiben, ist dies implizit self->node
.)
Also ist die verwendete Variable this
und es wird this
erfasst. (Technisch% this
wird im Standard als eigener eigener Ausdruckstyp beschrieben, nicht als Variable, aber in jeder Hinsicht fungiert sie als implizite lokale Variable vom Typ Worker *const
.) Wie bei allen nicht __block
Variablen, wenn es erfasst wird, wird eine const
Kopie von this
erstellt.
Blöcke verfügen über Speicherverwaltungssemantik, wenn sie eine Variable des Objekt-Zeigertyps Objective-C erfassen. % Co_de% hat jedoch keinen Objective-C Objektzeigertyp, daher wird in Bezug auf die Speicherverwaltung nichts unternommen. (Es gibt nichts, was in Bezug auf die C ++ - Speicherverwaltung getan werden kann.) Also, das C ++ - Objekt, auf das this
zeigt, könnte bis zur Ausführung des Blocks ungültig sein.
Tags und Links objective-c objective-c++ block