手机
当前位置:查字典教程网 >编程开发 >php教程 >深入解析PHP的引用计数机制
深入解析PHP的引用计数机制
摘要:PHP的变量声明并赋值后,变量名存在符号表中,而值和类信息存在zval中,zval中包含四个变量,is_ref,refcount,value...

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

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;

查看refcount,is_ref,zval的变化

执行完第一部分后来看看输出

1-----------------------------

a:(refcount=3, is_ref=0),int 1

b:(refcount=3, is_ref=0),int 1

c:(refcount=3, is_ref=0),int 1

可以看出来a,b,c使用同一个zval

再看执行完第二部分的

2----------------------------

a:(refcount=2, is_ref=1),int 1

b:(refcount=2, is_ref=0),int 1

c:(refcount=2, is_ref=0),int 1

d:(refcount=2, is_ref=1),int 1

注意此时a,d在一起了,他们使用同一个zval,而bc使用一个新生成的zval,同时重新计算两个zval的refcount和is_ref

3----------------------------

a:(refcount=2, is_ref=1),int 2

b:(refcount=2, is_ref=0),int 1

c:(refcount=2, is_ref=0),int 1

d:(refcount=2, is_ref=1),int 2

可以知道ad这两个is_ref=1的好基友的值是同时改变的

4----------------------------

a:(refcount=2, is_ref=1),int 2

b:(refcount=1, is_ref=0),null

c:(refcount=1, is_ref=0),int 1

d:(refcount=2, is_ref=1),int 2

bc由于他们的zval的is_ref=0,所以他们不是好基友,他们的值不会同时改变,于是bc的zval再次分裂,b = null c = 1

【深入解析PHP的引用计数机制】相关文章:

透析PHP的配置文件php.ini

PHP调用三种数据库的方法(2)

自定义PHP分页函数

PHP SPL标准库中的常用函数介绍

PHP的开合式多级菜单程序

如何使用PHP中的字符串函数

PHP调用三种数据库的方法(3)

了解PHP的返回引用和局部静态变量

PHP中的一些常用函数收集

PHP输入输出流学习笔记

精品推荐
分类导航