PHP變量、引用、函數傳參之完全掌握,今後節操是路人

今天絕對是興奮的一天,不單單是週五這個特殊的日子(週六日能夠休息啦),也不是弄清了某wordpress插件的功能流程,更不是再次買到了想吃好久的手撕牛肉,而是真正解決了一直以來(嘿嘿,其實時間不長)對PHP中變量引用和函數傳參的疑惑。 php

故事源於一個巧合,我在查PHP變量做用域的東西時看到的文章(後面再附上地址,無心侵權做者大大)。由於這篇只講變量和函數傳參的,因此其餘的不涉及了(也無力涉及哈哈)。 html

看這麼一句 wordpress

$a = 'abc';

當咱們定義一個變量時,PHP會爲咱們作兩件事情 函數

  1. 申請一個zval結構體,那什麼是zval呢
    struct _zval_struct {
            /* Variable information */
            zvalue_value value;             /* value */
            zend_uint refcount;
            zend_uchar type;        /* active type */
            zend_uchar is_ref;
    };
    這個就是zval的C語言定義,在PHP中變量都是用這個結構體來存儲,其中成員zvalue_value是一個聯合體,用以存儲底層強類型變量,這種結構也是實現PHP弱類型的關鍵,在這裏只須要清楚有這麼個結構體就能夠了。
  2. zval結構體存實際內容(最最裏面實際上是那個union體),令變量名符號a指向這個zval,而後將a存在一個symbol_table中,這個symbol_table跟變量的做用域有關,這裏不作討論,只需知道一個變量是一個符號指向一個zval結構體就好。 
看下面代碼:
$a = 12;
$b = $a;

執行到第二句時,會在symbol_table中新加入b,令b指向a所指向的那個zval結構體,這個zval的refcount加1, 到這根據以往的知識可能就有疑問了,b指向a指向的結構體不就是引用了嘛,再看下面代碼: ui

$a = 12; $b = &$a;

那這算什麼?執行第二句時,除了在symbol_table中加入b令其指向a指向的那個zval並使refcount加1外,還會改變該zval中is_ref值爲1(默認爲零應該),is_ref是個bool值,用來標識這個變量是不是屬於引用集合(reference set)這樣這個zval就與一開始不太同樣了。 spa

來看更復雜的: .net

$a = 12;
$b = $a;
$c = &$a;

前兩行執行完與前面第一個例子是同樣的,此時$a和$b指向的zval的refcount值爲2,is_ref爲0,表示有兩個symbol指向這個zval, is_ref爲0,表示zval不屬於引用集合,當第三行執行時時,發現zval的refcount不爲1且不是引用集合,那麼便爲$b複製一個zval結構體,同時$a的zval的refcount減1,又由於多了$c指向原來的zval,因此又refcount加1,仍是2,同時$a也是$c的zval的is_ref置1,表示這個zval屬於引用集合了,$b的zval則是新的zval(refcount=1,is_ref=0)。 插件

第二、3行交換位置最後的結果相同,只不過zval的變化順序不一樣,最終仍然是$a與$c指向同一個zval(refcount=2,is_ref=1),$b指向的zval(refcount=1,is_ref=0)。 code

再有$d、$e等原理同樣。 orm

當更改變量時也會發生zval的新建與變化,原理同上,不細討論了,可參見:

  1. http://php.net/manual/zh/features.gc.refcounting-basics.php(複合類型的變量也有講到)
  2. http://www.laruence.com/2008/09/19/520.html(L大大寫的真的很棒) 

當咱們明白了這個機制的時候,函數傳參就迎刃而解了:

$a = 12;
function change($k){
    $k = 1;
}

change(&$a);  //至關於$k = &$a,接下來就知道怎麼辦了吧,$a的值是能夠改變的



change($a);   //至關於$k = $a,你看,還用我說麼?
好的,到這就差很少了,要是我寫的有點亂很差懂(不是深奧,我有自知之明的),好好研究下上面兩個網址。

恩,這篇寫的好累,休息休息 

相關文章
相關標籤/搜索