天天看點

深入了解PHP中指派與引用

          先看下面的問題:

  對于中間的那個問題,你的答案是什麼呢?在今天之前,我的答案是會為b配置設定記憶體空間。因為我是這麼了解的:

  &指派的時候,視為一個變量定義了一個别名,增加了一個對記憶體空間的引用。改變其中一個,會影響其他的引用。而使用unset()時,隻是斷開了對變量記憶體空間的引用,記憶體空間不會釋放。

  而 = 指派則不同,它會重新開辟一份記憶體空間存儲原變量的副本。兩者之間的修改不會互相影響。

而下面的程式則印證了這一點:

那如果  

  有這麼一個問題,如果 = 指派之後,兩個變量都不曾改變,如果是兩份副本,豈不是太浪費記憶體?

     PHP中實際上避免了這種情況。

  PHP中将一個變量指派給新變量時,不會立即為新變量配置設定記憶體空間,隻是增加了對記憶體空間的引用。當原變量或者新變量作出任何改變時,才會為新變量 配置設定一塊記憶體空間。

  每個php變量存在一個叫"zval"的變量容器中。一個zval變量容器,除了包含變量的類型和值,還包括兩個位元組的額外資訊。第一個是"is_ref",是個bool值,用來辨別這個變量是否是屬于引用集合(referenceset)。通過這個位元組,php引擎才能把普通變量和引用變量區分開來,由于php允許使用者通過使用&amp;來使用自定義引用,zval變量容器中還有一個内部引用計數機制,來優化記憶體使用。第二個額外位元組是"refcount",用以表示指向這個zval變量容器的變量(也稱符号即symbol)個數。當"refcount"的值是1時,"is_ref"的值總是<code>FALSE</code>. 

  安裝xdebug之後,利用xdebug_debug_zval(),可以看到zval結構:

  如下:

  

  輸出:

b:

int 

由上面的結果可以看到,在a作出改變之前,引用計數是2 ,當a作出改變之後,b的引用計數變為1,是因為b重新配置設定了空間