首先,让我们回顾zval结构:
复制代码代码如下所示:
结构_zval_struct {
变量信息
zvalue_value值; / * * /
zend_uint引用计数;
zend_uchar型活跃型; / * * /
zend_uchar is_ref;
};

引用计数和is_ref领域从未被介绍,而且我们知道PHP是一种服务器端脚本解释器的长期运行。它的效率和资源占用率是一个很重要的措施。也就是说,PHP必须尽可能地引入内存占用率。考虑下面的代码。
复制代码代码如下所示:
< PHP
$ var =laruence ;
var_dup美元= $ VaR;
unset($变量);
>

第一行创建了一个字符串变量,应用一个9字节的存储器,保存字符串laruence和空结束(/ 0)。
第二行定义一个新的字符串变量,并将变量var的值复制到新变量。
第三行设置变量
这段代码在我们平常的脚本中很常见,如果PHP为每个变量赋值分配内存,复制数据,那么公众就把这个代码应用到18字节的内存空间中,我们可以很容易地看到上面的代码,实际上不需要两个连续的空间,呵呵,PHP开发人员也读出了:
我们之前提到的,PHP变量存储在symbol_table符号名称,对应一个变量来实现的,如第一行代码将存储一个值VaR在symbol_table,这相当于一个指针指向一个结构变量,存储在laruence这个变量变量的值,所以它不难想象,在上面的代码中,我们可以使VAR指针和相应的var_dup指向同一个变量上。
这是PHP做的,这时我们需要引入引用计数字段在zval结构,我们还没有介绍过。
引用计数,顾名思义,记录当前的变量被引用的数量。
例如,对于代码:
复制代码代码如下所示:
< PHP
$ var = 1;
var_dup美元= $ VaR;
>

在第一行,一个塑料的变量是1个变量的值创建的。在这一点上,引用计数的变量是保存为塑料1 1。
第二行创建一个新的整形变量。变量也指向zval刚刚创建的,并增加了变量的引用计数为1,当这个变量的引用计数是2。
PHP提供了一个函数来帮助我们理解过程debug_zval_dump:
复制代码代码如下所示:
< PHP
$ var = 1;
debug_zval_dump($变量);
var_dup美元= $ VaR;
debug_zval_dump($变量);
>

输出:
长(1)引用计数(2)
长(1)引用计数(3)

如果你奇怪,VaR的引用计数应该是1
我们知道,对于简单的变量,PHP是一个转让价值形式的参数,也就是说,当执行debug_zval_dump($变量)时,美元将通过价值VaR debug_zval_dump,这将导致增加引用计数1无功,只要我们可以看到,当变量分配给一个变量,会导致变量引用计数和这个事实可以1。
现在让我们看看代码在文章的开头,如果设置的最后一行($变量)的执行是的,引用计数减1,上面的代码:
复制代码代码如下所示:
< PHP
$ var =laruence ;
var_dup美元= $ VaR;
unset($变量);
debug_zval_dump($ var_dup);
>

输出:
字符串(8)laruence引用计数(2)

但是下面的代码呢
复制代码代码如下所示:
< PHP
$ var =laruence ;
var_dup美元= $ VaR;
$ var = 1;
>

很明显,这段代码被执行后,var_dup美元价值应laruence,那么这是真的吗
这是PHP的复制写机制:
PHP在修改一个变量,变量将首先检查引用计数,如果引用计数大于1,PHP将上述代码执行一个单独的程序,当执行到第三行,PHP发现VaR点美元zval引用计数大于1,那么PHP将被复制到一个新的变量了原始变量引用计数减1,并修改symbol_table美元,使美元VaR和var_dup分离(分离)。这种机制称为写时复制(写时复制)。
上代码测试:
复制代码代码如下所示:
< PHP
$ var =laruence ;
var_dup美元= $ VaR;
$ var = 1;
debug_zval_dump($变量);
debug_zval_dump($ var_dup);
>

输出:
长(1)引用计数(2)
字符串(8)laruence引用计数(2)

现在我们知道,复制一个变量时,PHP不是一个真正的拷贝,而是一个尽可能节省成本的相同结构,那么,PHP中的引用是如何实现的呢
复制代码代码如下所示:
< PHP
$ var =laruence ;
var_ref美元= $ VaR;
var_ref = 1美元;
>

在这段代码结束后,var也将被间接地修改为1,这个过程被称为(改变写:写时间的变化)。
在zval的is_ref字段用于在这个时候:
上述代码,当第二行执行,通过VAR成为美元2代表变量引用计数,并is_ref设置在1同时。
在第三行中,PHP检查is_ref场变量,var_ref代表第一,如果是1,它是分不开的,和一般的逻辑如下:
复制代码代码如下所示:
如果((* Val)-> is_ref | |(*值>引用计数<2)){
不执行分离
;…/过程
}

但是,问题又来了。下面的代码会发生什么情况
复制代码代码如下所示:
< PHP
$ var =laruence ;
var_dup美元= $ VaR;
var_ref美元= $ VaR;
>

在上面的代码中,有一对变量的拷贝和写的VaR和var_dup美元美元,和一双写改变机制变量VAR和var_ref美元美元,这种情况下如何工作
当第二行是执行,如前所述,var_dup美元美元和VAR指向相同的变量,并引用计数是2。
当执行第三行,PHP发现机制要操作的引用计数大于1,那么PHP执行分离,分离var_dup美元,使美元和美元var_ref做VaR写改变相关,引用计数为2,is_ref = 1;
基于这样的分析,我们可以给debug_zval_dump的引用计数的结果1:
复制代码代码如下所示:
< PHP
$ var =laruence ;
var_dup美元= $ VaR;
debug_zval_dump($变量);
>

输出:
字符串(8)laruence引用计数(1)

有了理由,只要你能给读者一点分析,我就不为别人;
这一次我们介绍了PHP的变量分离机制,下一次我将继续介绍PHP脚本中的参数,如果它是从扩展中接收和发送的。