今天看了一下鸟哥博客变量的分离和引用的内容, 就作了一个笔记!php
$var = "I have a dream"; $var2 = $var; $var3 = $var;
若是咱们咱们建立一个变量就分配一次内存, 那么像上边的代码,那么就会形成内存的极大浪费. php中的变量是一个指向zval
的符号, 那么咱们就能够在zval中来优化上边的代码!php
的zval
中有一个recount
字段, 用来记录当前zval
被引用的次数html
$var = "abc"; //refcount = 1 $varCopy = $var; //refcount = 2
建立第一个变量$var
时refcount
的值为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
, 执行这段代码的时候$var
的refcount
又增长了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
指向的zval
的refcount
大于1, 那么php
就会复制一个新的zval
出来, 将原来的zval
的refcount
减1,并修改变量符号表, 是$var
指向新的zval
结构 1.这样原来的$var
和$varCopy
就各自指向了不一样的结构. 这个就是code
copy one write 也叫写时复制htm
若是咱们再加上引用的状况, 那么整个过程就会更加复杂!内存
$var = "abc"; $varRef = &$var; $varRef = 1;
最终$var
的结果是1, 这个过程被称为get
change on write 写时改变博客
此次的复制是不须要进行变量分离的,须要用到zval
的is_ref
字段, 对于上边的代码, 当第二行执行之后, $var
所表明的zval
的refcount
变为2, 同时设置is_ref
为1.
第三行的时候, php
会首先检查$varRef
的zval
的is_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)
就至关于对一个全新的变量执行!