深入理解PHP中赋值与引用
? ? ? ? ? 先看下面的問題:
<?php $a = 10;//將常量值賦給變量,會(huì)為a分配內(nèi)存空間$b = $a;//變量賦值給變量,是不是copy了一份副本,b也分配了內(nèi)存空間呢?$c = &$a;//引用是不會(huì)為c分配空間的,c和a是共用一份空間的。?>對(duì)于中間的那個(gè)問題,你的答案是什么呢?在今天之前,我的答案是會(huì)為b分配內(nèi)存空間。因?yàn)槲沂沁@么理解的:
&賦值的時(shí)候,視為一個(gè)變量定義了一個(gè)別名,增加了一個(gè)對(duì)內(nèi)存空間的引用。改變其中一個(gè),會(huì)影響其他的引用。而使用unset()時(shí),只是斷開了對(duì)變量?jī)?nèi)存空間的引用,內(nèi)存空間不會(huì)釋放。
而 = 賦值則不同,它會(huì)重新開辟一份內(nèi)存空間存儲(chǔ)原變量的副本。兩者之間的修改不會(huì)相互影響。
而下面的程序則印證了這一點(diǎn):
<?php $a = 10;//將常量值賦給變量,會(huì)為a分配內(nèi)存空間$b = $a;//變量賦值給變量,是不是copy了一份副本,b也分配了內(nèi)存空間呢?$c = &$a;//引用是不會(huì)為c分配空間的,c和a是共用一份空間的。$a = 5; echo $c;//輸出5,因?yàn)閍和c 是指向同一個(gè)內(nèi)存空間 echo PHP_EOL; echo $b;//由于b是副本,對(duì)a的操作不會(huì)影響b,輸出10 ?>那如果 ?
$b = $a;//之后a 和 b 都不做任何改變,保持一致有這么一個(gè)問題,如果 = 賦值之后,兩個(gè)變量都不曾改變,如果是兩份副本,豈不是太浪費(fèi)內(nèi)存?
? ? ?PHP中實(shí)際上避免了這種情況。
PHP中將一個(gè)變量賦值給新變量時(shí),不會(huì)立即為新變量分配內(nèi)存空間,只是增加了對(duì)內(nèi)存空間的引用。當(dāng)原變量或者新變量作出任何改變時(shí),才會(huì)為新變量 分配一塊內(nèi)存空間。
<?php $a = 1; $b = $a;echo $a; //在此之前,b都是和a共用內(nèi)存空間的。$a = 2;//a作出了改變,此時(shí)b才會(huì)有自己的空間 ?>每個(gè)php變量存在一個(gè)叫"zval"的變量容器中。一個(gè)zval變量容器,除了包含變量的類型和值,還包括兩個(gè)字節(jié)的額外信息。第一個(gè)是"is_ref",是個(gè)bool值,用來標(biāo)識(shí)這個(gè)變量是否是屬于引用集合(referenceset)。通過這個(gè)字節(jié),php引擎才能把普通變量和引用變量區(qū)分開來,由于php允許用戶通過使用&來使用自定義引用,zval變量容器中還有一個(gè)內(nèi)部引用計(jì)數(shù)機(jī)制,來優(yōu)化內(nèi)存使用。第二個(gè)額外字節(jié)是"refcount",用以表示指向這個(gè)zval變量容器的變量(也稱符號(hào)即symbol)個(gè)數(shù)。當(dāng)"refcount"的值是1時(shí),"is_ref"的值總是FALSE.?
安裝xdebug之后,利用xdebug_debug_zval(),可以看到zval結(jié)構(gòu):
如下:
<?php $a = 1; $b = $a;echo $a; //在此之前,b都是和a共用內(nèi)存空間的。 xdebug_debug_zval('b'); $a = 2;//a作出了改變,此時(shí)b才會(huì)有自己的空間 xdebug_debug_zval('b'); ?>
輸出:
b:
(refcount=2, is_ref=0),int?
1b:
(refcount=1, is_ref=0),int?
1由上面的結(jié)果可以看到,在a作出改變之前,引用計(jì)數(shù)是2 ,當(dāng)a作出改變之后,b的引用計(jì)數(shù)變?yōu)?,是因?yàn)閎重新分配了空間
?
?
?
總結(jié)
以上是生活随笔為你收集整理的深入理解PHP中赋值与引用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linq语言集成查询
- 下一篇: php实现数值的整数次方