Ursache des Problems
Vor zwei Tagen stellte jemand eine Frage zu new und stdClass in der Gruppe. Die spezifische Leistung ist wie folgt:
<?php $a = new stdClass; $b = new $a; var_dump($a, $b);
Dieser Code kann korrekt ausgeführt werden . Und $a und $b sind zwei verschiedene leere Objekte. Auch wenn Attribute hinzugefügt und Werte zu $a vor new $a zugewiesen werden, ist $b immer ein leeres Objekt.
Die Frage ist also: Warum können leere Objekte auf neue folgen? Gibt es etwas Besonderes an stdClass?
Tatsächliche Leistung
Tatsächlich kann dies durch eine kleine Überprüfung festgestellt werden. Tatsächlich hat dies nichts mit stdClass zu tun. Es wird beispielsweise vollständig durch das Verhalten von new bestimmt. Führen Sie einen einfachen Test auf psysh durch:
>>> $a = new Reflection; => Reflection {#174} >>> $b = new $a; => Reflection {#177}
Hier habe ich eine neue Instanz der Reflection-Klasse erstellt, die sich genauso verhält wie stdClass. Natürlich können Sie auch eine Klasse anpassen:
>>> class Test { public $foo = 1; } => null >>> $a = new Test => Test {#178 +foo: 1, } >>> $a->foo = 2; => 2 >>> $b = new $a; => Test {#180 +foo: 1, }
An diesem Beispiel können wir deutlich erkennen, dass das Ändern der Attribute von $a keine Auswirkungen auf $b hat (Sie können auch über einen PHP-Schlüsselwort: Klon nachdenken ).
Da wir nun die Leistung kennen, können wir auch die Schlussfolgerung ziehen: Das Erstellen eines neuen Objekts durch ein Objekt einer neuen Klasse entspricht der neuen Klasse des ursprünglichen Objekts.
Ursache
Welche Art von PHP-Implementierung verursacht dieses Verhalten? Beginnen wir mit dem Quellcode, um dieses Problem zu analysieren.
Tatsächlich können wir vom Quellcode aus direkt zu zend_vm_def.h gehen, um die Antwort zu finden. In der Erklärung des Opcodes ZEND_FETCH_CLASS können wir Folgendes sehen:
ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMPVAR|UNUSED|CV) { ... if (OP2_TYPE == IS_CONST) { ... } else if (Z_TYPE_P(class_name) == IS_OBJECT) { Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name); } ... ... }
Einige Störungen beseitigen Im Kontext stellt der obige Inhalt eindeutig eine Erklärung dar: Wenn der erhaltene Klassenname ein Objekt ist, wird seine Klasse über das Makro Z_OBJCE_P gefunden. Die obige Leistung ist also leicht zu erklären.
Dies ist an sich eine sehr einfache Frage, es besteht keine Notwendigkeit, kompliziert darüber nachzudenken. Wenn Sie die spezifische Implementierung von new erfahren möchten, können Sie in der Datei zend_compile.c die Implementierung von zend_compile_new anzeigen.