源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

深入解析PHP的引用计数机制

  • 时间:2022-11-15 23:13 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:深入解析PHP的引用计数机制
PHP的变量声明并赋值后,变量名存在符号表中,而值和类信息存在zval中,zval中包含四个变量,[b]is_ref,refcount,value,type,zval[/b]源码如下
[u]复制代码[/u] 代码如下:
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”两种状态 [b]此处分析一下什么时候zval会被复制或者开辟新的内存空间呢 [/b]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的值类型,宏定义如下
[u]复制代码[/u] 代码如下:
#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的值,他也是个共同体,代码如下
[u]复制代码[/u] 代码如下:
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来决定是用共同体里的哪个变量来存值的 [b]见下面的例子1 [/b]
[u]复制代码[/u] 代码如下:
.----------- $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
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部