gpt4 book ai didi

深入PHP变量存储的详解

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 25 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章深入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状态切换 当在一个zval上进行的所有赋值操作都是引用或者都是非引用时,一个is_ref就足够应付了。然而,世界总不会那么美好,PHP无法对用户进行这种限制,当我们混合使用引用和非引用赋值时,就必须要进行特别处理了。 情况I、看如下PHP代码:

复制代码 代码如下:

<?php
$a = 1;
$b = $a;
$c = $b;
$d = &$c; // 在一堆非引用赋值中,插入一个引用
?>

这段代码首先进行了一次初始化,这将创建一个新的zval,is_ref=0, refcount=1,并将a指向这个zval;之后是两次非引用赋值,正如前面所说,只要把b和c都指向a的zval即可;最后一行是个引用赋值,需要is_ref为1,但是Zend发现c指向的zval并不是引用型的,于是为c创建单独的zval,并同时将d指向该zval。 从本质上来说,这也可以看作是一种Copy-On-Write,不仅仅是value,is_ref也是受保护的对象。 整个过程图示如下:

  。

深入PHP变量存储的详解

情况II,看如下PHP代码:

复制代码 代码如下:

<?php
$a = 1;
$b = &$a;
$c = &$b;
$d = $c; // 在一堆引用赋值中,插入一个非引用
?>

这段代码的前三句将把a、b和c指向一个zval,其is_ref=1, refcount=3;第四句是个非引用赋值,通常情况下只需要增加引用计数即可,然而目标zval属于引用变量,单纯的增加引用计数显然是错误的, Zend的解决办法是为d单独生成一份zval副本。 全过程如下所示:

  。

深入PHP变量存储的详解

1.1.5 参数传递 PHP函数参数的传递和变量赋值是一样的,非引用传递相当于非引用赋值,引用传递相当于引用赋值,并且也有可能会导致执行zval状态切换。这在后面还将提到.

最后此篇关于深入PHP变量存储的详解的文章就讲到这里了,如果你想了解更多关于深入PHP变量存储的详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com