众所周知,PHP是不支持指针的,但是如果希望两个变量同时指向同一内存块怎么办呢?为了解决这个问题,PHP内核里使用了引用计数器。
上篇博文介绍了PHP变量在内核中的存储方式了,zval结构中下面两个成员变量用于引用计数器:
is_ref BOOL值,标识变量是否是引用集合。
refcount 计算指向引用集合的变量个数。
看下面的php代码
<?php
$a = "this is a";
?>
一个zval结构的实体称为zval容器。在php语言层创建一个变量就会相应地在php内核中创建一个zval容器。因为上面的代码创建了一个变量$a,所以在php内核中会创建一个zval容器;又因为这个变量不是一个引用,所以zval容器的is_ref等于FALSE,并且refcount等于1.
再看下面的代码
<?php
$a = "this is a";
$b=$a;
?>
上面这段代码创建了两个变量
写时复制,就是当变量的值改变时才进行内存的复制。要理解写时复制,先看下面的代码:
<?php
$a="this is a";
xdebug_debug_zval(‘a‘);
$b=$a;
xdebug_debug_zval(‘a‘);
$a="changed value";
xdebug_debug_zval(‘a‘);
?>
上面这段代码使用xdebug调试工具。输出的结果如下:
a:
{refcount=1,is_ref=0} string ‘this is a‘ {length=10}
a:
{refcount=2,is_ref=0} string ‘this is a‘ {length=10}
a:
{refcount=1,is_ref=0} string ‘changed value‘ {length=13}
上面所示,当将变量refcount
的值变回1,所以这时变量
看最后一种情况,如果用户在php脚本中显式地让一个变量引用另一个变量,php内核会如何处理呢?看下面的代码:
<?php
$a=1;
xdebug_debug_zval(‘a‘);
$b=&$a;
xdebug_debug_zval(‘a‘);
$b+=5;
xdebug_debug_zval(‘a‘);
?>
上面的代码输出结果为:
a:
{refcount=1,is_ref=0} int 1
a:
{refcount=2,is_ref=1} int 1
a:
{refcount=2,is_ref=1} int 6
可以看到,当显式地让一个变量引用另一个变量时,变量的is_ref字段会设置为1,表示此变量被引用,另外引用计数器(refcount)也相应的加1,。而在php内核中通过下面代码判断是否复制变量:
if((*valval)->is_ref ||(*valval)->refcount<2 ) {
return $valval;
}
从上面的代码中可以知道,当变量被引用或者计数器小于2时会直接返回变量的指针(直接返回变量的实体,而不复制变量的值)。当修改一个被引用变量的值时,所有引用它的变量其值也会被修改,因为它们指向同一个zval容器。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/hzk_wen/article/details/47172169