Einführung in Objekte und Referenzen im PHP-Speicher

Veröffentlicht: 2022-03-11

Ich habe diesen Artikel zum ersten Mal während meines Studiums für meine PHP-Zertifizierung verfasst, um besser zu verstehen, wie PHP Variablen und Objekte im Speicher verwaltet. Nach viel Recherche wurde mir klar, dass es nicht einfach war, Antworten auf meine Fragen zu finden, und als ich fertig war, beschloss ich, die Informationen zu dokumentieren, damit die Leute sie alle an einem Ort finden können.

In diesem Artikel werde ich darüber sprechen, wie Objekt- und Variablenreferenzen im Speicher gesteuert werden, da dies ein Thema ist, das Diskussionen und unterschiedliche Meinungen hervorrufen kann. Eine Frage zum Nachdenken ist: „Werden Objekte in PHP standardmäßig per Referenz oder per Kopie übergeben?“ Ich werde zuerst darüber sprechen, welche Referenzen nicht in PHP vorkommen; Zweitens werde ich diskutieren, was sie sind , und schließlich werde ich untersuchen, wie der Garbage Collector in PHP funktioniert.

Wie erstellt PHP Objekte im Speicher, wenn eine Anweisung wie $a = new Foo(); ? Heutzutage ist Speicher nicht mehr so ​​teuer und eine begrenzte Ressource wie früher. Dennoch ist es für gute PHP-Entwickler wichtig zu wissen und zu verstehen, wie Variablen und Objekte während der Ausführung ihrer Anwendung intern verwaltet werden.

Objekte und Referenzen im PHP-Speicher und PHP-Garbage-Collection

Objekte und Referenzen in PHP

Viele Leute sagen – in PHP-Büchern und online –, dass Objekte in PHP standardmäßig als Referenz übergeben werden. Andere sagen, dass Objekte in PHP per Kopie zugewiesen werden. Um herauszufinden, welche Aussage richtig ist, müssen wir zunächst analysieren, was eine Referenz in PHP ist (und was nicht).

Was sind keine Referenzen in PHP?

Wichtiger als zu wissen, was Referenzen in PHP sind, ist zu wissen, was sie nicht sind. In PHP sind Referenzen keine Zeiger im C-Stil; Sie können mit Referenzen keine arithmetischen Operationen ausführen wie mit C-Zeigern. Warum? Denn anders als in C sind PHP-Referenzen eigentlich keine Speicheradressen, da es sich nicht um Zahlen handelt, die einen Speicherort angeben. Aber was sind Referenzen?

Was sind Referenzen in PHP?

In PHP sind Referenzen „Aliase“, die es zwei verschiedenen Variablen ermöglichen, einen einzelnen Wert zu lesen und zu schreiben. Anders ausgedrückt handelt es sich um Mechanismen, die den Zugriff auf denselben Wert von Variablen mit unterschiedlichen Namen ermöglichen, sodass sie sich so verhalten, als wären sie dieselbe Variable. Denken Sie daran, dass in PHP Variablennamen und der Inhalt von Variablen zwei völlig verschiedene Dinge sind, die in der sogenannten „Symboltabelle“ verknüpft sind. Wenn wir also eine Referenz erstellen, fügt sie einfach einen Alias ​​für diese Variable in der Symboltabelle hinzu. Angenommen, wir haben den folgenden Code:

 $a = new Foo();

Wenn die obige Anweisung ausgeführt wird, wird die Variable $a im Speicher erstellt, ein Objekt vom Typ Foo wird im Speicher erstellt und der Symboltabelle wird ein Eintrag hinzugefügt, der angibt, dass die Variable $a „referenziert“ (oder sich auf sie bezieht). , oder zeigt auf das Foo -Objekt, oder wie auch immer Sie es nennen möchten), aber es ist per se kein Zeiger auf dieses Objekt. Konzeptionell haben wir so etwas wie diese Abbildung:

Objektreferenzen im PHP-Speicher

Pop-Quiz: Was passiert, wenn wir das ausführen?

 $b = $a;

Es ist nicht so, dass $b eine Referenz von $a wird; wir können auch nicht sagen, dass $b eine Kopie von $a ist. Was wirklich passiert ist, ist, dass wir eine neue Variable $b im Speicher erstellt und dann einen neuen Eintrag in der Symboltabelle hinzugefügt haben, der anzeigt, dass die Variable $b auch auf dasselbe Foo -Objekt verweist wie $a . Visuell haben wir also etwas Ähnliches wie in dieser Abbildung:

Objektreferenzen im PHP-Speicher

Wenn wir nun ausführen:

 $c = &$a;

Wir haben eine dritte Variable $c im Speicher erstellt, aber keinen neuen Eintrag in der Symboltabelle für $c . Stattdessen wird in der Symboltabelle aufgezeichnet, dass $c ein Alias ​​für $a ist, also verhält es sich identisch, aber $c ist kein Zeiger auf $a – anders als in C, das etwas namens Zeiger auf Zeiger erzeugt. Zur Veranschaulichung haben wir etwas Ähnliches wie in dieser Abbildung gezeigt:

Diagramm der Variablen und ihrer Aliase

Sobald wir den Wert einer dieser drei Variablen ändern wollen (dh einen neuen Wert schreiben), muss PHP eine neue z_val Struktur im Speicher erstellen, um den Inhalt der Variablen $b und das Paar $a / zu trennen. $c , sodass sie unabhängig voneinander geändert werden können, ohne den Wert des anderen zu beeinflussen. Wenn wir also die folgende Zeile zum vorherigen Skript hinzufügen:

 $b = new Bar();

In Erinnerung haben wir eine Situation wie in der folgenden Abbildung dargestellt:

Grafische Darstellung der oben beschriebenen Situation

Betrachten wir nun ein vollständigeres Beispiel:

 <?php class myClass { public $var; function __construct() { $this->var = 1; } function inc() { return ++$this->var; } } $a = new myClass(); // $a "references" a Foo object $b = $a; //b also references the same Foo object as a //($a) == ($b) == <id> of Foo object, but a and b are different entries in symbols table echo "$a = ";var_dump($a); echo "$b = ";var_dump($b); $c = &$a; //$c is an alias of $a //($a, $c) == <id> of Foo object, c is an alias of a in the symbols table echo "$c = ";var_dump($c); $a = NULL; //The entry in the symbols table which links "$a" with Foo object is removed //Since that entry was removed, $c is not related to Foo anymore //Anyway, Foo still exists in memory and it is still linked by $b echo "$a = ";var_dump($a); echo "$b = ";var_dump($b); echo "$c = ";var_dump($c); echo "$b->var: ".$b->inc(); echo "$b->var: ".$b->inc(); $b = NULL; //The entry in the symbols table which links "$b" with the Foo object is removed //There are no more entries in the symbols table linked to Foo, //So, Foo is not referenced anymore and can be deleted by the garbage collector echo "$b = ";var_dump($b);

Die Ausgabe, die durch die Implementierung des obigen Skripts erzeugt wird, lautet:

 $a = object(myClass)#1 (1) { ["var"]=> int(1) } $b = object(myClass)#1 (1) { ["var"]=> int(1) } $c = object(myClass)#1 (1) { ["var"]=> int(1) } $a = NULL $b = object(myClass)#1 (1) { ["var"]=> int(1) } $c = NULL $b->var: 2 $b->var: 3 $b = NULL

PHP-Garbage-Collection

Lassen Sie uns abschließend sehen, wie die PHP-Garbage-Collection funktioniert, seit sie in Version 5.3 eingeführt wurde. Ein Objekt oder eine Variable im PHP-Speicher wird vom PHP-Garbage Collector entfernt, wenn es keine Verweise auf dieses Objekt in der Symboltabelle gibt. Das heißt, PHP verwaltet einen Referenzzähler eines Objekts ab dem Zeitpunkt seiner Erstellung, so dass der Zähler während der Ausführung des PHP-Skripts diesen Referenzzähler basierend auf den Variablen, die darauf „zeigen“, erhöht und verringert. Sobald die Referenzanzahl 0 erreicht (dh nichts verweist auf dieses Objekt und wird es daher nicht verwendet), markiert PHP dieses Objekt als entfernbar, sodass es beim nächsten Durchlauf des PHP-Garbage-Collectors aus dem Speicher entfernt wird , wodurch dieser Speicherplatz für die Wiederverwendung freigegeben wird. Wenn Sie weitere Einzelheiten zur Funktionsweise der PHP-Garbage-Collection wünschen, lesen Sie diese Dokumentation.

Abschließende Gedanken

Ich hoffe, ich habe ein wenig klargestellt, wie PHP mit Objekten und Variablen im Speicher umgeht und wie es die Objekte „auswählt“, die vom PHP-Garbage Collector entfernt werden sollen.

Nachdem Sie nun verstanden haben, wie PHP Variablen und Objekte im Speicher intern verwaltet, schnappen Sie sich Ihren Laptop und beginnen Sie, mit etwas Code zu experimentieren, um zu beweisen, was Sie gelernt haben. Versuchen Sie, mit Variablen und Referenzen herumzuspielen. Experimentieren Sie auch damit, wie sich das Ändern des Werts einer Variablen auf den Wert einer anderen Variablen auswirken könnte, die darauf verweist. Hier ist eine Frage an Sie: Was werden die Werte von $a und $b sein, nachdem der folgende Code ausgeführt wurde?

 $a = '1'; $b = &$a; $b = "2$b";

Wenn Sie mehr über PHP-Leistungsmerkmale erfahren möchten, lesen Sie diesen Beitrag von Toptaler Vilson Duka.