今天看了一下鳥哥博客變量的分離和引用的內容, 就作了一個筆記!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)
就至關於對一個全新的變量執行!