深刻理解PHP中賦值與引用

原文: 深刻理解PHP中賦值與引用

          先看下面的問題:php

<?php 
$a = 10;//將常量值賦給變量,會爲a分配內存空間

$b = $a;//變量賦值給變量,是否是copy了一份副本,b也分配了內存空間呢?

$c = &$a;//引用是不會爲c分配空間的,c和a是共用一份空間的。

?>

  對於中間的那個問題,你的答案是什麼呢?在今天以前,個人答案是會爲b分配內存空間。由於我是這麼理解的:html

  &賦值的時候,視爲一個變量定義了一個別名,增長了一個對內存空間的引用。改變其中一個,會影響其餘的引用。而使用unset()時,只是斷開了對變量內存空間的引用,內存空間不會釋放。post

  而 = 賦值則不一樣,它會從新開闢一分內存空間存儲原變量的副本。二者之間的修改不會相互影響。優化

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

<?php 
$a = 10;//將常量值賦給變量,會爲a分配內存空間

$b = $a;//變量賦值給變量,是否是copy了一份副本,b也分配了內存空間呢?

$c = &$a;//引用是不會爲c分配空間的,c和a是共用一份空間的。

$a = 5;
echo $c;//輸出5,由於a和c 是指向同一個內存空間
echo PHP_EOL;
echo $b;//因爲b是副本,對a的操做不會影響b,輸出10
?>

那若是  spa

$b = $a;//以後a  和  b 都不作任何改變,保持一致

  有這麼一個問題,若是 = 賦值以後,兩個變量都未曾改變,若是是兩份副本,豈不是太浪費內存?debug

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

  PHP中將一個變量賦值給新變量時,不會當即爲新變量分配內存空間,只是增長了對內存空間的引用。當原變量或者新變量做出任何改變時,纔會爲新變量 分配一塊內存空間。htm

<?php 
$a = 1;
$b = $a;

echo $a;
//在此以前,b都是和a共用內存空間的。

$a = 2;//a做出了改變,此時b纔會有本身的空間
?>

  每一個php變量存在一個叫"zval"的變量容器中。一個zval變量容器,除了包含變量的類型和值,還包括兩個字節的額外信息。第一個是"is_ref",是個bool值,用來標識這個變量是不是屬於引用集合(referenceset)。經過這個字節,php引擎才能把普通變量和引用變量區分開來,因爲php容許用戶經過使用&來使用自定義引用,zval變量容器中還有一個內部引用計數機制,來優化內存使用。第二個額外字節是"refcount",用以表示指向這個zval變量容器的變量(也稱符號即symbol)個數。當"refcount"的值是1時,"is_ref"的值老是FALSEblog

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

  以下:

  

<?php 
$a = 1;
$b = $a;

echo $a;
//在此以前,b都是和a共用內存空間的。
xdebug_debug_zval('b');
$a = 2;//a做出了改變,此時b纔會有本身的空間
xdebug_debug_zval('b');
?>

  輸出:

b:

(refcount=2, is_ref=0),

int 

1

b:

(refcount=1, is_ref=0),

int 

1

由上面的結果能夠看到,在a做出改變以前,引用計數是2 ,當a做出改變以後,b的引用計數變爲1,是由於b從新分配了空間

相關文章
相關標籤/搜索