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. 這個是我本身猜測的, 不知道是否正確.請輸入代碼
相關文章
相關標籤/搜索