PHP
—
基础 PHP 的引用计数机制
本文是对 PHP 中的引用计数机制进行详细的分析介绍,需要的朋友参考下
PHP 的变量声明并赋值后,变量名存在符号表中,而值和类信息存在 zval 中,zval 中包含
四个变量,
is_ref,refcount,value,type,zval
源码如下
struct _zval_struct {
/* Variable information */
zvalue_value value;
/* value */
zend_uint refcount__gc;
zend_uchar type;
/* active type */
zend_uchar is_ref__gc;
};
refcount 表示 value 地址与其相同的 zval 共有多少个,refcount=0 时,zval 被销毁
is_ref 表示一个 zval
“
是否被引用,有 0” “
和 1”两种状态
此处分析一下什么时候 zval 会被复制或者开辟新的内存空间呢
1.当 is_ref=0,且 refcount>1 时,如果改变某个指向该 zval 的变量的值,会生成新 zval,原
zval 的 refcount--,例如:$a=1;$b=$a;$b=2;,zval 将被复制,也就是说原先 ab 指向同一个
zval,后来 b 会使用新开辟的 zval
2.当 is_ref=0,且 refcount>1 时,如果将 zval 赋值给某个引用变量,那么用来赋值和变量和
被赋值的变量会使用同一个原 zval,而其他指向原 zval 的变量将会指向一个新复制的
zval,且 refcount 会被重新计算,例如:$a=1;$b=$a;$c=$a;$d=&$a;,此时 ad 使用原 zval,bc
使用新复制出来的 zval
3.当 is_ref=1,且 refcount>1 时,如果将 zval 复制给某个非引用变量,该非引用变量会使用
一个新复制的 zval,元 zval 的 refcount 不变,例如:$a=1;$b=&$a;$c=$a,那么 ab 使用原
zval,而 c 使用新复制的 zval
type 表示该 zval 的值类型,宏定义如下
#define
IS_NULL
0
#define
IS_LONG
1
#define
IS_DOUBLE
2
#define
IS_BOOL
3
#define
IS_ARRAY
4
#define
IS_OBJECT
5
#define
IS_STRING
6
#define
IS_RESOURCE
7
#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY 9