php 变量分离和引用

PHP 变量的分离和引用

今天看了一下鸟哥博客变量的分离和引用的内容, 就作了一个笔记!php

$var = "I have a dream";
$var2 = $var;
$var3 = $var;

若是咱们咱们建立一个变量就分配一次内存, 那么像上边的代码,那么就会形成内存的极大浪费. php中的变量是一个指向zval的符号, 那么咱们就能够在zval中来优化上边的代码!
phpzval中有一个recount字段, 用来记录当前zval被引用的次数html

$var = "abc";           //refcount = 1
$varCopy = $var;        //refcount = 2

建立第一个变量$varrefcount的值为1, 当建立第二个变量$varCopy时, refcount的值为2.咱们怎么能查看到这个值呢, 能够经过php提供的debug_zval_dump输出变量的内容和refcount函数

$var = "abc";               //refcount = 1
debug_zval_dump($var);      //string(3) "abc" refcount(2)
$varCopy = $var;            //refcount = 2
debug_zval_dump($var);      //string(3) "abc" refcount(3)

为何打印的结果和咱们预想的结果不一致呢, 函数debug_zval_dump有一个值传递的形参, 就至关于又执行了一次$arg = $var, 执行这段代码的时候$varrefcount又增长了1,因此在debug_zval_dump内部打印的结果就比实际的要大1.若是咱们对一个变量进行unset那么会是一种什么样的效果呢优化

$var = "abc";
$varCopy = $var;
unset($var);
debug_zval_dump($varCopy);      //string(3) "abc" refcount(2)

若是像下边这段代码会发生什么呢:debug

$var = "abc";
    $varCopy = $var;
    $var = 1;

若是一个变量被从新赋值, 在赋值的过程当中会首先检测refcount的值, 若是refcount大于1, php就会执行一个分离过程.上边的代码在执行到第三行的时候, php发现$var指向的zvalrefcount大于1, 那么php就会复制一个新的zval出来, 将原来的zvalrefcount减1,并修改变量符号表, 是$var指向新的zval结构 1.这样原来的$var$varCopy就各自指向了不一样的结构. 这个就是code

copy one write 也叫写时复制htm

若是咱们再加上引用的状况, 那么整个过程就会更加复杂!内存

$var = "abc";
$varRef = &$var;
$varRef = 1;

最终$var的结果是1, 这个过程被称为get

change on write 写时改变博客

此次的复制是不须要进行变量分离的,须要用到zvalis_ref字段, 对于上边的代码, 当第二行执行之后, $var所表明的zvalrefcount变为2, 同时设置is_ref为1.
第三行的时候, php会首先检查$varRefzvalis_ref字段,若是为1, 则不分离.

$var = "abc";
$varCopy = $var;
$varRef = &$var;

上边的状况, 存在copy on write 同时也有change on write, 是怎么运做的呢.
当执行第二行的时候和前边的copy on write同样, $var$varCopy指向相同的zval,refcount为2
当执行第三行的时候, php发现要操做的zval($var所指向的zval)的refcount大于1, php就会执行分离操做, 把$varCopy分离出去, 并将$var$varRef作change on write关联, 也就是refcount=2, is_ref=1
若是整个过程反过来2

$var = "abc";       //refcount=1, is_ref=0
$varRef = &$var;    //refcount=2, is_ref=1
$varCopy = $var;    //refcont=1, is_ref=0

第三行代码, 由于上边的变量$var对应的zval有is_ref的存在, 那么当前的变量就会直接复制一份出来, 而不会触发copy on write机制.

咱们在看一段代码

$var = "abc";
$varRef = &$var;
debug_zval_dump($var);  //string(3) "abc" refcount(1)

这个结果和预想的又有所差异, 是什么缘由的? debug_zval_dump() 须要一个值传递的形参, 那么执行debug_zval_dump($var)的时候就至关于debug_zval_dump($arg = $var) 这样就会形成变量的分离,在debug_zval_dump($arg)就至关于对一个全新的变量执行!


  1. 这个地方按个人理解应该是要全新生成一个zval, 而后修改原来的zval的refcount
  2. 这个是我本身猜测的, 不知道是否正确.请输入代码
相关文章
相关标签/搜索