PHP的引用計数基础知识.doc
文本预览下载声明
PHP 的引用计数基础知识
PHP MYSQL 2010-05-22 22:14:52 阅读12 评论0 ??字号:大中小?订阅
PHP 的引用计数基础知识
2010-4-9 11:18:00
一个php变量存储在一个叫做“zval” 的地方,一个zval 结构包含了什么呢,包含了变量的类型和值,和两个附加信位元信息,第一个位叫做“is_ref”, 它是个布尔值,它标识了这个变量是不是个引用类型,通过这个位元,PHP引擎了解了这个变量是普通类型的变量还是引用类型的变量。因为php允许通过 操作符让用户获得一个引用。一个zval容器则通过一个叫做引用技术的机制来优化内存的占用。附加的两个位第二个位叫做”refcount”,包含了有多少变量名(这里叫做symbols)指向了这 “一个”zval容器。 Php的所有变量符号保存在一个叫做符号表的地方,并且保存每一个变量的周期和范围。范围包括完整的周期,或者每一个函数或方法内部。
当一个变量通过一个常量值建立的时候,一个zval 容器被建立。例如:
?php ??? $a= new string; ? 在上例中, 一个新的符号名“a” 被建立在当前范围内(作用域),并且建立了一个类型为“string”,值为”new string” 的新的变量容器, 这时因为目前还没有个用户建立的引用指向它,所以 “is_ref”默认为false, “refcount” 被设置为1,表示只有一个符号被用于这个变量容器。注意,如果”refcount” 为1,则”is_ref”永远为”false”. 如果你使用 xdebug ,可以通过它开查看响应信息:
?php ? Xdebug_debug_zval(‘a’); ? 将会显示:
a: (refcount=1, is_ref=0) = ‘new string’ 下面,赋值给其他变量名,将增加引用计数
?php $a= new string; $b= $a; xdebug_debug_zval(‘a’); ? 将会显示:
?a:(refcount =2,is_ref=0) = new string 这里 refcount 为 2,因为同一个变量容器连接到了符号“a” 和”b”, php 有足够的聪明判断是否在不需要一个实际的变量容器的时候而复制一个,当”refcount”变为0的时候,变量容器将被摧毁, 当连接到变量容器的变量符号离开作用域(比如,函数结束)或者在符号表上调用unset()的时候,”refcount” 将会被减少1, 下面的例子说明了这个:
?php $a =new string; $c =$b = $a; xdebug_debug_zval(a); unset($b,$c); xdebug_debug_zval(a); ? 将会显示:
a :(refcount = 3,is_ref=0)=’new sring’ a: (refcount=1,is_ref=0) = ‘new string’ 如果我们现在调用”unset(a);”则变量容器,包括内部的值和类型,将会从内存移出.
复合类型
在数组和对象 等复合类型上,事情变得有点复杂,和标量类型不同的是,数组和对象分别保存它们的属性在它们自己的一个符号表内。 下面的例子将会建立三个zval容器:
?php $a= array(meaning=life,number=42); xdebug_debug_zval(a); ? 将会显示:
a: (refcount=1,is_ref=0) = array( meaning= (refcount=2,is_ref=0) = life, number=(refcount=1,is_ref=0)=42, ) 或者用图表示:
点击查看大图
这三个zval 容器分别为 “a”,”meaning” 和”number”,简单的规则同样适用于它们对”refcount” 的增减:
我们添加一个其他的元素到一个存在的数组:
?php $a= array(meaning=life,number=42); $a[life]= $a[meaning]; xdebug_debug_zval(a); ? 将会显示:
a: (refcount=1,is_ref=0) = array( meaning=(refcount=2,is_ref=0)= life, number=(refcount=1,is_ref=0)= 42, life=(refcount=2,is-ref=0)=life ) ?
用图来显示:
点击查看大图
通过上面的xdebug输出, 我们看到新的数组元素和旧的元素现在指向了一个
显示全部