手机版

PHP变量存储的详细说明

时间:2021-11-19 来源:互联网 编辑:宝哥软件园 浏览:

1.1.1 zval结构Zend使用zval结构存储PHP变量的值,如下所示:复制代码如下: TypeDef Union _ ZValue _ Value { long lval;/*长值*/double dval;/*双精度值*/struct { char * val;int len} strHashTable * ht/*哈希表值*/Zend _ object _ value obj;} zvalue _ valuestruct _zval_struct {/*变量信息*/zvalue _ value;/* value */Zend _ uint ref count;zend_uchar类型;/*活动类型*/Zend _ uchar is _ ref;};typedef struct _ zval _ struct zvalZend根据类型值决定访问哪个值成员。以下值可用:IS_NULLN/AIS_LONG对应值. lvalIS_DOUBLE对应值. dvalIS_STRING对应值. strIS_ARRAY对应值. htIS_OBJECT对应值. lval.IS_RESOURCE对应值. lval可以根据此表发送。有两个有趣的地方:首先,PHP的数组实际上是一个HashTable,这解释了PHP为什么可以支持关联数组;其次,Resource是长值,通常存储指针、内部数组的索引或者只有创建者自己知道的东西,可以看作句柄。1.1.2引用计数引用计数广泛应用于垃圾收集、内存池、字符串等场所,因此Zend实现了典型的引用计数。很多PHP变量可以通过引用计数机制共享同一个zval,而zval中剩下的两个成员就是_ ref和refcount来支持这种共享。显然,refcount用于计数。当参考值增加或减少时,该值也会相应地增加或减少。一旦降至零,Zend将回收zval。is_ref呢?1.1.3 zval状态在PHP中,有——引用和非引用两种变量,通过引用计数的方式存储在Zend中。对于非引用变量,要求变量之间互不相关。修改变量时,不能影响其他变量。这种冲突可以通过采用写时复制机制来解决。——当试图写入一个变量时,Zend复制一个refcount为1的zval,并递减原始zval的refcount。这个过程被称为“zval分离”。但是对于引用变量,要求与非引用变量相反,引用赋值的变量必须绑定。修改一个变量会修改所有绑定变量。因此,有必要指出zval的当前状态,以分别处理这两种情况。这是is_ref的用途,它指示指向此zval的所有变量是否都是通过引用分配的——,要么是所有引用,要么是无引用。此时修改另一个变量,Zend只有在发现其zval is_ref为0时才会执行写时复制,即不是引用。1.1.4 zval状态切换当zval上的所有赋值操作都是引用或非引用时,一个is_ref就足够了。然而,世界永远不会如此美好。PHP不能这样限制用户。当我们混合引用和非引用赋值时,我们必须特别处理它。一、看下面的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。本质上,这也可以被视为写时复制,它不仅是一个值,也是一个受保护的对象。整个过程说明如下:

案例二,看看下面的PHP代码:复制代码如下:PHP $ a=1;$ b=$ a;$ c=$ b;$ d=$ c;//在引用分配堆中插入非引用?这段代码的前三句将a、b和c指向一个zval,其is _ ref=1,ref count=3;第四句是非引用赋值,通常只需要增加引用数即可。但是,由于目标zval属于引用变量,因此简单地增加引用计数显然是错误的。Zend的解决方案是为d单独生成一个zval的副本,整个过程如下:

1.1.5参数传递PHP函数参数传递与变量赋值相同,非引用传递相当于非引用赋值,引用传递相当于引用赋值,也可能导致zval状态切换。这个后面会提到。

版权声明:PHP变量存储的详细说明是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。