先看一段小代码
$a = 3;
$b = $a;
$b = 5;
echo $a . PHP_EOL . $b; // 3 5
$a = 3;
$b = &$a;
$b = 5;
echo $a . PHP_EOL . $b; // 5 5
很明显可以看出,第一段小代码上赋值,第二段是引用赋值 下面来解析一下上面2步操作在zend engine中发生了什么。
对于第一段和第二段代码来说首先$a = 3
这个操作在ZE里都是一样,产生了一个struct
的变量结构体。类似下面这样
第二部的时候开始出现了变化, $b = $a
和$b = &$a
$b = $a
注意这里红框标识的,因为$b只是$a的一个副本,所以ze直接把$a的结构体refcount_gc
这个值+1。而对于$b = &$a我们来看看发生了什么。
第三行分析 ($b = 5
)
当结构体中有2个变量指向的时候,任何一方修改都会导致结构体分裂 (copy on write)
对于第一个示例来说$b = 5意味着ZE中的结构体开始分裂,产生了另外一个结构体也就是$b = 5的这个新的结构体。而此时原来$a = 3这个结构体重的refcount_gc
-1操作 如下图
那么对于第二个示例来说,$b = 5的时候结构体不分裂,而是直接修改对应地址的值,即修改$a的值,从3修改成5。
学习整理:PHP内存中变量赋值和引用