Recently I was looking at the reference counter part in PHP. First I was confused by all kinds of confusion. Then after reading blogs and analyzing it, I summarized a relatively simple explanation, which can help me remember it well, and I hope it can also help all readers. . Sharing a blog post here is a more orthodox explanation: PHP variable reference (http://hilojack.sinaapp.com/?p=1392).
To study changes in PHP reference counters, you can learn by installing the Xdebug extension. After installation, call xdebug_debug_zval('var') directly to see the reference counter of the variable $var.
Talking about reference counters requires an understanding of the storage and reference counting mechanisms of variables in PHP. Reference counting, of course, saves memory. It allows multiple variable symbols to share a memory value space without affecting the semantic correctness ( Also called variable container). When the reference count changes: Assignment. There are two types of assignment: transfer-by-value assignment and assignment by reference. What is more difficult to understand is reference assignment. Another function of reference counting is to indicate when the same space can be shared and when variables must be separated (new space is opened).
In order to facilitate understanding and memory, I give popular explanations of various scenarios in assignment, and do not match the actual situation, .
The ampersand sign is combination, which can be equivalent to marriage, but PHP allows multiple people to marry together (i.e. polygamy or polyandry), which is quite abnormal. Note You must live together to get married, living apart is not acceptable. In addition to marriage, there is another form called shared housing. Sharing is also living together, but there is no relationship. It is reasonable and reasonable to allow multiple people to live together. Of course, there is another situation, which is easier to understand, is living alone. The following example illustrates the correspondence between assignment statements and these three states:
Scenario 1:
$a = "a"; // $a 独居, is_ref = 0, refcount = 1; $b = $a; // $a 与 $b 合租, is_ref = 0, refcount = 2;
$a = "a"; // $a 独居, is_ref = 0, refcount = 1; $b = &$a; // $a 与 $b 结婚, is_ref = 1, refcount = 2;
The following begins to analyze the variable change relationship during assignment:
Scenario 1:
$a = "a";  // $a 独居, is_ref = 0, refcount = 1; $b = $a;   // $a 与 $b 合租, is_ref = 0, refcount = 2; $va = "b"; // $va 独居, is_ref = 0, refcount = 1; $vb = $va; // $va 和 $vb 合租, is_ref = 0, refcount = 2; $a = $va;  // $a是单身,$va也是单身,因此 $a 搬去与 $va 同居,现在$a,$va,$vb三人同居 赋值后:  $a: is_ref = 0, refcount = 3, string = "xyz" $b: is_ref = 0, refcount = 1, string = "qwe" $va: is_ref = 0, refcount = 3, string "xyz" $vb: is_ref = 0, refcount = 3, string "xyz"
$a = "a";  // $a 独居, is_ref = 0, refcount = 1; $b = &$a;   // $a 与 $b 结婚, is_ref = 1, refcount = 2; $va = "b"; // $va 独居, is_ref = 0, refcount = 1; $vb = $va; // $va 和 $vb 合租, is_ref = 0, refcount = 2; $a = $va;  // $a是已婚, $a 不能随便单独搬出去,赋值会使$va的值拷贝给$a,其他<strong>关系</strong>不变 $a: is_ref = 1, refcount = 2, string = "xyz" $b: is_ref = 1, refcount = 2, string = "xyz" $va: is_ref = 0, refcount = 2, string "xyz" $vb: is_ref = 0, refcount = 2, string "xyz"
$a = "a";  // $a 独居, is_ref = 0, refcount = 1; $b = &$a;   // $a 与 $b 结婚, is_ref = 1, refcount = 2; $va = "b"; // $va 独居, is_ref = 0, refcount = 1; $vb = &$va; // $va 和 $vb 结婚, is_ref = 1, refcount = 2; $a = $va;  // $a是已婚, 与情景二相同,值拷贝,关系不变 赋值后: $a: is_ref = 1, refcount = 2, string = "xyz" $b: is_ref = 1, refcount = 2, string = "xyz" $va: is_ref = 1, refcount = 2, string "xyz" $vb: is_ref = 1, refcount = 2, string "xyz"
$a = "qwe"; // $a 独居, is_ref = 0, refcount = 1; $b = $a; // $a 与 $b 同居, is_ref = 0, refcount = 2; $va = "xyz"; // $va 独居, is_ref = 0, refcount = 1; $vb = &$va; // $va 和 $vb 结婚, is_ref = 1, refcount = 2; $a = $va; // $a 想与 $va同居(而非结婚),但是$va已婚的,因此 $a只能从$b那里搬出来,重新分配个房子,值与$va一样(术语叫:变量分离);$va和$vb关系不变 赋值后: $a: is_ref = 0, refcount = 1, string = "xyz" $b: is_ref = 0, refcount = 1, string = "qwe" $va: is_ref = 1, refcount = 2, string "xyz" $vb: is_ref = 1, refcount = 2, string "xyz"
$a = "qwe"; // $a 独居, is_ref = 0, refcount = 1; $b = $a; // $a 与 $b 同居, is_ref = 0, refcount = 2; $va = "xyz"; // $va 独居, is_ref = 0, refcount = 1; $vb = $va; // $va 和 $vb 同居, is_ref = 0, refcount = 2; $a = &$va; // $a 想与 $va结婚,现在$a 和 $va 都是单身但是都有室友了,因此他们各自从原来的地方搬出来,然后分个新房子,值与$va原来的一样 赋值后: $a: is_ref = 1, refcount = 2, string = "xyz" $b: is_ref = 0, refcount = 1, string = "qwe" $va: is_ref = 1, refcount = 2, string "xyz" $vb: is_ref = 0, refcount = 1, string "xyz"
$a = "qwe"; // $a 独居, is_ref = 0, refcount = 1; $b = $a; // $a 与 $b 同居, is_ref = 0, refcount = 2; $va = "xyz"; // $va 独居, is_ref = 0, refcount = 1; $vb = &$va; // $va 和 $vb 结婚, is_ref = 1, refcount = 2; $a = &$va; // $a 想与 $va 结婚,但是 $va 是已婚的,而 $a 是单身,因此 $a 搬过去和 $va 住,$va 现在有两个配偶:$vb 和 $a 赋值后: $a: is_ref = 1, refcount = 3, string = "xyz" $b: is_ref = 0, refcount = 1, string = "qwe" $va: is_ref = 1, refcount = 3, string "xyz" $vb: is_ref = 1, refcount = 3, string "xyz"
$a = "qwe"; // $a 独居, is_ref = 0, refcount = 1; $b = &$a; // $a 与 $b 结婚, is_ref = 1, refcount = 2; $va = "xyz"; // $va 独居, is_ref = 0, refcount = 1; $vb = $va; // $va 和 $vb 同居, is_ref = 0, refcount = 2; $a = &$va; // $a 想与 $va 结婚,但是 $a 是已婚的,$va 是单身, 解决办法是 $a 离婚后和 $va 结婚,同时 $va 从与 $vb合租的地方搬出来 赋值后: $a: is_ref = 1, refcount = 2, string = "xyz" $b: is_ref = 0, refcount = 1, string = "qwe" $va: is_ref = 1, refcount = 2, string "xyz" $vb: is_ref = 0, refcount = 1, string "xyz"
$a = "qwe"; // $a 独居, is_ref = 0, refcount = 1; $b = &$a; // $a 与 $b 结婚, is_ref = 1, refcount = 2; $va = "xyz"; // $va 独居, is_ref = 0, refcount = 1; $vb = &$va; // $va 和 $vb 结婚, is_ref = 1, refcount = 2; $a = &$va; // $a 想与 $va 结婚,但是 $a和$va都是已婚的,谁离婚?$a!,因为是$a主动想和$va结婚, // $a 离婚后$va住一起,$va 现在有两个配偶:$vb 和 $a 赋值后: $a: is_ref = 1, refcount = 3, string = "xyz" $b: is_ref = 0, refcount = 1, string = "qwe" $va: is_ref = 1, refcount = 3, string "xyz" $vb: is_ref = 1, refcount = 3, string "xyz"
Simple assignment means cohabitation. You need to check the is_ref of the variable on the left side of the equal sign (that is, whether you are married). If is_ref = 1, copy the value. Otherwise, consider the left side of the order to see if it can be done without allocating additional memory. , sharing the same storage space (cohabitation) with the variable on the right side. At this time, it is necessary to check whether the right side is married. If so, they cannot live together and the variables are separated. If the variable on the right side is also single, they directly share the same memory, and all cohabitants are Follow the COW (copy-on-write) principle.
Reference assignment is a combination. You need to check the reference status of the variable on the right side first. If is_ref = 1, directly refcount ++. If there is a combination of multiple people, if the right side is non-referenced (is_ref = 0), then still It is necessary to check whether the person on the right side lives alone. If he lives alone, the two variables on the left and right share the variable space on the right side. Otherwise, the variable on the right side is separated from the original place and a new space is opened on the left side. As long as it is a reference assignment, the left-hand variable must always be separated from the previously combined or shared variable.