深入解析PHP的引用计数机制
发布时间:2020-12-13 06:22:44 所属栏目:PHP教程 来源:网络整理
导读:PHP的变量声明并赋值后,变量名存在符号表中,而值和类信息存在zval中,zval中包含四个变量, is_ref,refcount,value,type,zval 源码如下 代码如下: struct _zval_struct { /* Variable information */ zvalue_value value; /* value */ zend_uint refcount_
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”两种状态 1.当is_ref=0,且refcount>1时,如果改变某个指向该zval的变量的值,会生成新zval,原zval的refcount--,例如:$a=1;$b=$a;$b=2;,zval将被复制,也就是说原先ab指向同一个zval,后来b会使用新开辟的zval2.当is_ref=0,且refcount>1时,如果将zval赋值给某个引用变量,那么用来赋值和变量和被赋值的变量会使用同一个原zval,而其他指向原zval的变量将会指向一个新复制的zval,且refcount会被重新计算,例如:$a=1;$b=$a;$c=$a;$d=&$a;,此时ad使用原zval,bc使用新复制出来的zval3.当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 value表示该zval的值,他也是个共同体,代码如下 代码如下: typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { char *val; int len; } str; HashTable *ht; /* hash table value */ zend_object_value obj; } zvalue_value; 现在你知道php是如何类型变换的了,因为他的值存的其实是个可以代表任何类型的结构体,而具体的取值则根据type来决定是用共同体里的哪个变量来存值的 见下面的例子1 代码如下: .----------- $a = 1; $b = $a; $c = $a; .----------- $d = &$a; .----------- $a = 2; .----------- $b = null; 执行完第一部分后来看看输出 1----------------------------- a:(refcount=3,is_ref=0),int 1 b:(refcount=3,int 1 c:(refcount=3,int 1 再看执行完第二部分的 2---------------------------- a:(refcount=2,is_ref=1),int 1 b:(refcount=2,int 1 c:(refcount=2,int 1 d:(refcount=2,int 1 注意此时a,d在一起了,他们使用同一个zval,而bc使用一个新生成的zval,同时重新计算两个zval的refcount和is_ref 3---------------------------- a:(refcount=2,int 2 b:(refcount=2,int 2 可以知道ad这两个is_ref=1的好基友的值是同时改变的 4---------------------------- a:(refcount=2,int 2 b:(refcount=1,null c:(refcount=1,int 2 bc由于他们的zval的is_ref=0,所以他们不是好基友,他们的值不会同时改变,于是bc的zval再次分裂,b = null c = 1 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |