PHP7 引用计数 读书笔记

每个php变量存在一个加"zval"的变量容器中。一个zval变量容器,除了包含变量的类型和值,还包括两个字节的额外信息。

1.is_ref :是一个bool值,用来标识这个变量是否属于引用集合。通过这个字节,php引擎才能把普通变量和引用变量区分开来,由于php允许用户通过&来自定义引用,zval变量容器中还有一个内部引用计数机制,来优化内存使用。

2.refcount,用来表示指向这个zval变量容器的变量(也称为符号symbol)个数。所有的符号存在一个符号表中,其中每个符号都有作用域,那些主脚本和每个函数或者方法也都有作用域。

接下来我们通过几个例子来帮助大家理解。(以下代码是在 Linux+php7.1环境下)

1.生成一个新的zval 容器

<?php
$a = 'new string';
xdebug_debug_zval('a');

 输出结果如下:

  

从结果可以看出 refount = 0,is_ref=0 那怎么理解这个输出结果呢?

(1)is_ref = 0 信息很容易理解,$a 不是一个引用变量自然就是0

(2)refount 的值怎么也是0,因为我们知道在php7中对于简单的数据类型,比如整型,字符串,浮点型等简单类型的值是直接存储在zval结构里面。

如果把变量a赋值给多个变量会怎样?

<?php
$a = "new string";
$c = $b = $a;
xdebug_debug_zval( 'a' );

 输出结果如下:

  

 发现refcount的值还是0,三个变量共用1个zval结构,没有存符号表。下面我们再给看下变量被引用后的情况:

<?php
$a = "new string";
$b = &$a;
$c = &$b ;
xdebug_debug_zval( 'a' );
xdebug_debug_zval( 'b' );
xdebug_debug_zval( 'c' );

 输出结果如下:

    

 我们发现三个变量的refount和is_ref都相同,那我们来解释下:

1.当变量被引用后,原来的zval结构会发生变化,php 会新增一个_zend_reference结构,这个结构会根据值得类型不同而不同。

struct _zend_reference {
      zend_refcounted_h gc;
      zval       val;
}

 我们来看下php的具体操作:

(1)php会申请一个zend_reference结构

(2)将zval_reference.value 指向原来的 zval_struct.value

(3)zval_struct.value 的数据类型修改为zend_refrence

(4)将zval_struct.value 指向刚刚申请并初始化的 zend_reference

(5)为新变量申请zval_struct 结构,将他的value 指向刚刚创建的zend_reference

猜你喜欢

转载自www.cnblogs.com/shuzhen2020/p/12196216.html
今日推荐