php语言 百分网手机站

深入PHP变量存储的详解

时间:2020-08-05 14:56:59 php语言 我要投稿

深入PHP变量存储的详解

  文章是对PHP变量的存储进行了详细的分析介绍,需要的朋友参考下,就跟随百分网小编一起去了解下吧,想了解更多相关信息请持续关注我们应届毕业生考试网!

  1.1.1 zval结构

  Zend使用zval结构来存储PHP变量的值,该结构如下所示:

  复制代码 代码如下:

  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;

  struct _zval_struct {

  /* Variable information */

  zvalue_value value;  /* value */

  zend_uint refcount;

  zend_uchar type;   /* active type */

  zend_uchar is_ref;

  };

  typedef struct _zval_struct zval;

  Zend根据type值来决定访问value的哪个成员,可用值如下:

  IS_NULL

  N/A

  IS_LONG

  对应value.lval

  IS_DOUBLE

  对应value.dval

  IS_STRING

  对应value.str

  IS_ARRAY

  对应value.ht

  IS_OBJECT

  对应value.obj

  IS_BOOL

  对应value.lval.

  IS_RESOURCE

  对应value.lval

  根据这个表格可以发现两个有意思的地方:首先是PHP的数组其实就是一个HashTable,这就解释了为什么PHP能够支持关联数组了;其次,Resource就是一个long值,它里面存放的通常是个指针、一个内部数组的index或者其它什么只有创建者自己才知道的东西,可以将其视作一个handle。

  1.1.2 引用计数

  引用计数在垃圾收集、内存池以及字符串等地方应用广泛,Zend就实现了典型的引用计数。多个PHP变量可以通过引用计数机制来共享同一份zval,zval中剩余的两个成员is_ref和refcount就用来支持这种共享。

  很明显,refcount用于计数,当增减引用时,这个值也相应的递增和递减,一旦减到零,Zend就会回收该zval。

  那么is_ref呢?

  1.1.3 zval状态

  在PHP中,变量有两种——引用和非引用的,它们在Zend中都是采用引用计数的.方式存储的。对于非引用型变量,要求变量间互不相干,修改一个变量时,不能影响到其他变量,采用Copy-On-Write机制即可解决这种冲突——当试图写入一个变量时,Zend若发现该变量指向的zval被多个变量共享,则为其复制一份refcount为1的zval,并递减原zval的refcount,这个过程称为“zval分离”。然而,对于引用型变量,其要求和非引用型相反,引用赋值的变量间必须是捆绑的,修改一个变量就修改了所有捆绑变量。

  可见,有必要指出当前zval的状态,以分别应对这两种情况,is_ref就是这个目的,它指出了当前所有指向该zval的变量是否是采用引用赋值的——要么全是引用,要么全不是。此时再修改一个变量,只有当发现其zval的is_ref为0,即非引用时,Zend才会执行Copy-On-Write。

  1.1.4 zval状态切换