深入理解PHP中賦值與引用
先看下面的問題:
<?php $a = 10;//將常量值賦給變數,會為a分配記憶體空間 $b = $a;//變數賦值給變數,是不是copy了一份副本,b也分配了記憶體空間呢? $c = &$a;//引用是不會為c分配空間的,c和a是共用一份空間的。 ?>
對於中間的那個問題,你的答案是什麼呢?在今天之前,我的答案是會為b分配記憶體空間。因為我是這麼理解的:
&賦值的時候,視為一個變數定義了一個別名,增加了一個對記憶體空間的引用。改變其中一個,會影響其他的引用。而使用unset()時,只是斷開了對變數記憶體空間的引用,記憶體空間不會釋放。
而 = 賦值則不同,它會重新開闢一份記憶體空間儲存原變數的副本。兩者之間的修改不會相互影響。
而下面的程式則印證了這一點:
<?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 ?>
那如果
$b = $a;//之後a 和 b 都不做任何改變,保持一致
有這麼一個問題,如果 = 賦值之後,兩個變數都不曾改變,如果是兩份副本,豈不是太浪費記憶體?
PHP中實際上避免了這種情況。
PHP中將一個變數賦值給新變數時,不會立即為新變數分配記憶體空間,只是增加了對記憶體空間的引用。當原變數或者新變數作出任何改變時,才會為新變數 分配一塊記憶體空間。
<?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”的值總是FALSE
.
安裝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重新分配了空間
相關文章
- php之普通變數賦值、物件賦值、引用賦值的區別PHP變數賦值物件
- JS中的變數賦值深入理解JS變數賦值
- php 傳值與傳引用的理解(通俗易懂)PHP
- 常被新手忽略的值賦值和引用賦值(偏redux向)賦值Redux
- PHP 物件導向 (四)類物件賦值為引用傳遞PHP物件賦值
- PHP引用的&理解PHP
- 理解Golang多重賦值Golang賦值
- php 自增賦值PHP賦值
- JAVA 物件引用,以及物件賦值Java物件賦值
- 給物件引用變數賦值(轉)物件變數賦值
- 自己對Java中if變數賦值的理解Java變數賦值
- PHP中陣列賦值效能及過程PHP陣列賦值
- C++左值引用與右值引用C++
- c++ 左值引用與右值引用C++
- 【c++】深賦值與淺賦值C++賦值
- 問題分享:Js引用型別賦值JS型別賦值
- 深入理解CSS中的margin負值CSS
- shell中變數的取值與賦值變數賦值
- 你真的理解Python中的賦值、傳參嗎?Python賦值
- php變數賦值給jsPHP變數賦值JS
- 值物件與引用物件物件
- 深入理解Java的分級引用模型Java模型
- 深入解析 ES6:解構賦值賦值
- php給$_POST賦值會導致值為空PHP賦值
- 深入理解PHP物件注入PHP物件
- Python 中變數賦值傳遞時的引用和複製介紹Python變數賦值
- vector訪問與賦值賦值
- C++11 左值引用和右值引用與引用摺疊和完美轉發C++
- 理解Java中的弱引用Java
- JAVA中鎖的深入理解與解析Java
- 深入理解 MVC 中的 M 與 CMVC
- Makefile中幾種賦值(= := ?= +=)賦值
- javascript賦值運算子等號=深入介紹JavaScript賦值
- Swift 中的值型別與引用型別使用指北Swift型別
- Kotlin 布林值教程:深入理解與應用示例Kotlin
- 值傳遞與引用傳遞
- 值型別與引用型別型別
- 深入理解PHP之strposPHP