Heim >Backend-Entwicklung >PHP-Problem >Was bedeutet Referenzzählung in PHP?

Was bedeutet Referenzzählung in PHP?

醉折花枝作酒筹
醉折花枝作酒筹nach vorne
2021-05-08 17:31:401811Durchsuche

Dieser Artikel führt Sie in die Referenzzählung von PHP ein. Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird für alle hilfreich sein.

Was bedeutet Referenzzählung in PHP?

Was ist Referenzzählung? In der Datenstruktur von PHP bezieht sich die Referenzzählung auf jede Variable. Zusätzlich zum Speichern ihres Typs und Werts werden auch zwei zusätzliche Inhalte gespeichert. und das andere ist die Anzahl der Zitate. Warum müssen wir zwei weitere Inhalte speichern? Natürlich für die Garbage Collection (GC).

Mit anderen Worten: Wenn die Anzahl der Referenzen 0 ist, wird diese Variable nicht mehr verwendet und kann über GC recycelt werden, um die belegten Speicherressourcen freizugeben.

Kein Programm kann Speicherressourcen auf unbestimmte Zeit belegen, was oft zu einem ernsthaften Problem führt, nämlich Speicherlecks, die die Zerstörung des Speichers für uns automatisch abschließen. Wie C muss manuell freigegeben werden.

Wie überprüfe ich die Referenzanzahl?

Wir müssen die xdebug-Erweiterung installieren und dann die Funktion xdebug_debug_zval() verwenden, um die detaillierten Informationen des angegebenen Speichers anzuzeigen, wie zum Beispiel:

$a = "I am a String";
xdebug_debug_zval('a');
// a: (refcount=1, is_ref=0)='I am a String'

Wie aus dem Obigen ersichtlich ist, ist der Inhalt dieser $a-Variablen Ich bin ein String wie dieser, ein String. Der Refcount in Klammern gibt die Anzahl der Referenzen an und is_ref gibt an, ob auf die Variable verwiesen wird. Sehen wir uns an, wie sich diese beiden Parameter durch die Variablenzuweisung ändern.

$b = $a;
xdebug_debug_zval('a');
// a: (refcount=1, is_ref=0)='I am a String'

$b = &$a;
xdebug_debug_zval('a');
// a: (refcount=2, is_ref=1)='I am a String'

Wenn wir eine normale Zuweisung durchführen, haben refcount und is_ref keine Änderungen, aber wenn wir eine Referenzzuweisung durchführen, können wir sehen, dass refcount 2 und is_ref 1 wird. Dies bedeutet, dass die aktuelle Variable $a durch Referenz zugewiesen wird und ihre Speichersymboltabelle die beiden Variablen $a und $b bedient.

$c = &$a;
xdebug_debug_zval('a');
// a: (refcount=3, is_ref=1)='I am a String'

unset($c, $b);
xdebug_debug_zval('a');
// a: (refcount=1, is_ref=1)='I am a String'

$b = &$a;
$c = &$a;
$b = "I am a String new";
xdebug_debug_zval('a');
// a: (refcount=3, is_ref=1)='I am a String new'

unset($a);
xdebug_debug_zval('a');
// a: no such symbol

Fügen Sie weiterhin eine Referenzzuweisung zu $c hinzu, und Sie können sehen, dass die Refanzahl weiter zunimmt. Nach dem Deaktivieren von $b und $c kehrt refcount auf 1 zurück. Es ist jedoch zu beachten, dass is_ref immer noch 1 ist. Das heißt, wenn auf diese Variable verwiesen wurde, wird is_ref zu 1, auch wenn die referenzierte Variable Even ist Wenn es nicht gesetzt wurde, bleibt der Wert unverändert.

Schließlich deaktivieren wir $a und die angezeigte Meldung enthält kein solches Symbol. Die aktuelle Variable wurde zerstört und ist keine verwendbare symbolische Referenz mehr. (Beachten Sie, dass Variablen in PHP der Speichersymboltabelle und nicht der tatsächlichen Speicheradresse entsprechen.)

Objektreferenzzählung

Wie gewöhnliche Typvariablen verwenden auch Objektvariablen dieselben Zählregeln.

// 对象引用计数
class A{

}
$objA = new A();
xdebug_debug_zval('objA');
// objA: (refcount=1, is_ref=0)=class A {  }

$objB = $objA;
xdebug_debug_zval('objA');
// objA: (refcount=2, is_ref=0)=class A {  }

$objC = $objA;
xdebug_debug_zval('objA');
// objA: (refcount=3, is_ref=0)=class A {  }

unset($objB);
class C{

}
$objC = new C;
xdebug_debug_zval('objA');
// objA: (refcount=1, is_ref=0)=class A {  }

Hier ist jedoch zu beachten, dass die Symboltabelle des Objekts eine etablierte Verbindung ist. Das heißt, eine erneute Instanziierung oder Änderung von $objC auf NULL hat keinen Einfluss auf den Inhalt von $objA Ist die vorherige Objektzuweisung eine Referenz in PHP? Es wurde bereits im Artikel erklärt. Gewöhnliche Zuweisungsoperationen für Objekte sind ebenfalls Symboltabellenzuweisungen von Referenztypen, sodass wir das &-Symbol nicht hinzufügen müssen.

Referenzzählung von Arrays

// 数组引用计数
$arrA = [
    'a'=>1,
    'b'=>2,
];
xdebug_debug_zval('arrA');
// arrA: (refcount=2, is_ref=0)=array (
//     'a' => (refcount=0, is_ref=0)=1, 
//     'b' => (refcount=0, is_ref=0)=2
// )

$arrB = $arrA;
$arrC = $arrA;
xdebug_debug_zval('arrA');
// arrA: (refcount=4, is_ref=0)=array (
//     'a' => (refcount=0, is_ref=0)=1, 
//     'b' => (refcount=0, is_ref=0)=2
// )

unset($arrB);
$arrC = ['c'=>3];
xdebug_debug_zval('arrA');
// arrA: (refcount=2, is_ref=0)=array (
//     'a' => (refcount=0, is_ref=0)=1, 
//     'b' => (refcount=0, is_ref=0)=2
// )

// 添加一个已经存在的元素
$arrA['c'] = &$arrA['a'];
xdebug_debug_zval('arrA');
// arrA: (refcount=1, is_ref=0)=array (
//     'a' => (refcount=2, is_ref=1)=1, 
//     'b' => (refcount=0, is_ref=0)=2, 
//     'c' => (refcount=2, is_ref=1)=1
// )

Beim Debuggen von Arrays werden wir zwei interessante Dinge finden.

Erstens hat jedes Element innerhalb des Arrays seinen eigenen separaten Referenzzähler. Dies ist auch einfacher zu verstehen. Jedes Array-Element kann als separate Variable betrachtet werden, das Array ist jedoch ein Hash-Satz dieser Variablen. Wenn das Objekt Mitgliedsvariablen enthält, tritt der gleiche Effekt auf. Wenn ein Element im Array durch & einer anderen Variablen zugewiesen wird, wird der Refcount dieses Elements erhöht, ohne dass sich dies auf den Refcount des gesamten Arrays auswirkt.

Zweitens beträgt der Standard-Refcount des Arrays 2. Tatsächlich handelt es sich hierbei um eine neue Funktion nach PHP7. Wenn ein Array definiert und initialisiert wird, wird es in ein unveränderliches Array (unveränderliches Array) umgewandelt. Um es von gewöhnlichen Arrays zu unterscheiden, beginnt der Refcount dieses Arrays bei 2. Wenn wir ein Element in diesem Array ändern, ändert sich das Array wieder in ein normales Array, d. h. refcount ändert sich wieder auf 1. Sie können dies selbst ausprobieren. Die offizielle Erklärung dient der Effizienz. Um das spezifische Prinzip zu ermitteln, müssen Sie sich möglicherweise noch mit dem PHP7-Quellcode befassen.

Was Sie bei Speicherlecks beachten sollten

Tatsächlich hat uns PHP bereits beim GC-Mechanismus auf der untersten Ebene geholfen, sodass wir uns nicht allzu viele Sorgen um die Zerstörung und Freigabe von Variablen machen müssen. Wir müssen jedoch dafür bezahlen Beachten Sie, dass Elemente in Objekten oder Arrays dies können Die Zuweisung ist eine eigene, dh die Zuweisung eines Verweises auf sich selbst zu einem Element wird zu einem Zirkelverweis. Dann ist es grundsätzlich unwahrscheinlich, dass dieses Objekt automatisch von GC zerstört wird.

// 对象循环引用
class D{
    public $d;
}
$d = new D;
$d->d = $d;
xdebug_debug_zval('d');
// d: (refcount=2, is_ref=0)=class D { 
//     public $d = (refcount=2, is_ref=0)=... 
// }

// 数组循环引用
$arrA['arrA'] = &$arrA;
xdebug_debug_zval('arrA');
// arrA: (refcount=2, is_ref=1)=array (
//     'a' => (refcount=0, is_ref=0)=1, 
//     'b' => (refcount=0, is_ref=0)=2, 
//     'arrA' => (refcount=2, is_ref=1)=...
// )

Ob es sich um ein Objekt oder ein Array handelt, wenn beim Drucken und Debuggen Auslassungspunkte wie ... erscheinen, dann gibt es in Ihrem Programm einen Zirkelverweis. Im vorherigen Artikel über das Kopieren von Objekten in PHP haben wir auch über dieses Zirkelverweisproblem gesprochen, daher sollten wir diesem Problem bei der täglichen Entwicklung immer Aufmerksamkeit schenken.


Empfohlenes Lernen:

php-Video-Tutorial

Das obige ist der detaillierte Inhalt vonWas bedeutet Referenzzählung in PHP?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen