引言
內容來自於《extending and embedding php》- chaper 3 - memory management,加上自己的理解,對php中變數的引用計數、寫時複製,寫時改變,寫時複製和改變做個」翻譯「。
zval
看下面的內容之前先對zval這個結構體做個了解
typedef struct _zval_struct zval;
zval結構體中共有4個元素,value是乙個聯合體,用來真正的儲存zval的值,refcount用來計數該zval被多少個變數使用,type表示zval所儲存的資料型別,is_ref用來標誌該zval是否被引用。
引用計數
<?php
$a = 'hello world';
$b = $a;
unset($a);
?>
我們一起來剖析下上面這段**:
unset($a);
這句**執行後,核心會將\(a對應的zval結構體中的refcount計數減一,\)b還和原來一樣
寫時複製
<?php
$a = 1;
$b = $a;
$b += 5;
?>
上面這段**執行完之後,一般肯定希望$a=1,$b=6
,但是如果像引用計數那樣,$a
和$b
指向相同的zval,修改$b
之後$a
不是也變了?
這個具體是怎麼實現的呢,我們一起來看下:
寫時改變
<?php
$a = 1;
$b = &$a;
$b += 5;
?>
上面這段**執行完之後一般希望是:$a == $b == 6
。這個又是怎麼實現的呢?
分離的問題
說道現在聰明的你可能已經看出點問題了,如果乙個zval結構體既有refcount計數又有is_ref引用這個時候怎麼辦?
<?php
$a = 1;
$b = $a;
$c = &$a;
?>
如果出現上面這種情況的時候,如果$a、$b、$c
指向同乙個zval結構體,進行改變的時候zend到底去聽誰的?其實這個地方不會指向同乙個zval了。
如果對乙個is_ref = 0 && refcount >1
的zval進行寫時改變這種賦值形式(就是引用賦值)的時候,zend會將等號右邊的變數分離出來乙個新的zval,
對這個zval進行初始化,對之前的zval的refcount進行減1操作,讓等號左邊的變數指向這個新的zval,refcount進行加1操作,is_ref=1。看看下面這張
上面這又是另外一種情況,在is_ref = 1
的情況下,試圖單純的進行refcount+1操作的時候會分離出來乙個新的zval給等號左邊的變數,並初始化他,看看下面這張
global和$globals['']
這兩個用的比交多的都是將全域性作用域下的變數引入到函式作用域,但是他們之間是有一點差距的。
global \(a 是全域性作用域的\)a的引用。
\(globals['a'] 是全域性作用域的\)a變數本身。
參考文獻
1.《extending and embedding php》- chaper 3 - memory management.
2. php中global與$globals['']區別
越努力,越幸運!越幸運,越努力!做上ceo不是夢
贏取白富美不是夢
屌絲逆襲不是夢
就是現在!!加油
php核心中的變數
php是弱型別語言,它可以儲存任何的資料型別。但是php是使用c語言編寫的,而c語言是強型別語言。每個變數都有固定的型別,不能隨意改變變數的型別。在zend zend.h中,檢視結構體 zval結構體就是通常用到的php變數在核心總的表示形式,在zval結構體中,可以看到四個成員變數,分別是 zva...
PHP核心探索 變數概述
現代程式語言中的基本元素主要有 變數,流程控制介面,函式等等我能否不使用變數來編寫程式呢?這顯然是可以的,例如 複製 如下 php echo hello andhm 這個程式很簡單,輸出乙個字串內容。就和我們僅僅使用二進位制也能程式設計一樣,不使用變數也能完成大部分的工作,不使用變數我們的程式將喪失...
PHP核心定義變數的方式
對於php的擴充套件開發和核心應用,寸謀的翻譯真心不錯,講的很有條理,只要大家回想起來c語言的基礎語法,這就不是問題。關於php的生命週期,以php變數在核心中的實現 感觸最深的就是變數檢索中的hashtable.php 核心中定義好了很多的函式來直接操作不同的資料型別,同一種方法,每個資料型別都有...