Objective C ++ Block Semantik

8

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?

    
Mark Bernstein 28.08.2013, 16:25
quelle

2 Antworten

8

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:

  • Er erfasst this und kopiert Instanzvariablen nicht nach Wert.
  • Nichts wird unternommen, um das Objekt auf 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 von node ? (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.

    
ipmcc 28.08.2013, 17:05
quelle
1

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.

    
newacct 28.08.2013 23:01
quelle