深入理解PHP7核心之Reference

2022-09-13 01:24:12 字數 2090 閱讀 4335

上一章說過引用(reference)在php5的時候是乙個標誌位, 而在php7以後我們把它變成了一種新的型別:is_refernce. 然而引用是一種很常見的應用, 所以這個變化帶來了很多的變化, 也給我們在做php7開發的時候, 因為有的時候疏忽忘了處理這個型別, 而帶來不少的bug.

最簡單的情況, 就是在處理各種型別的時候, 從此以後我們要多考慮這種新的型別, 比如在php7中, 這樣的**形式就變得很常見了:

try_again:

swtich (z_type_p(zv))

如果大家自己寫的擴充套件, 如果忘了考慮這種新的型別, 那麼就會導致問題.

那麼既然這種新型別會帶來這麼多問題, 那麼當時為什麼要用把引用變成一種型別呢? 為什麼不還是使用乙個標誌位呢?

一句話來說, 就是我們不得不這麼做. -_#

前面說到, hashtable直接儲存的是zval, 這樣在符號表中, 倆個zval如何共用乙個數值呢? 對於字串等複雜型別來說還好, 我們貌似可以在zend_refcounted結構中加入乙個標誌位來表明是引用來解決, 然而這個也會遇到change on write帶來的複製, 但是我們知道在php7中, 一些型別是直接儲存在zval中的, 比如is_long, 但是引用型別是需要引用計數的, 那麼對於乙個是is_long並且又是is_refernce的zval該如何表示呢?

為此, 我們創造了這個新的型別:

如圖所示, 引用是一種新的型別:zend_reference, 對於is_refernce型別的zval, zval.value.ref是乙個指向zend_reference的指標, 它包含了引用計數和乙個zval, 具體的zval的值是存在zval.value.ref->val中的.

所以對於is_long的引用來說, 就用乙個型別是is_refernce的zval, 它指向乙個zend_reference, 而這個zend_reference->val中是乙個型別為is_long的zval.

php採用引用計數來做簡單的垃圾**, 考慮如下的**:

<?php 

1. $val = "laruence";

2. $ref = &$val;

3. $copy = $val;

?>

$ref和$val是指向同乙個zval的引用, 在php5的時候, 我們是通過乙個引用計數為2, 並且引用標誌位為1來表示這種情況, 當把$val複製給$copy(line 3)的時候, 我們發現$val是乙個計數大於1的引用, 所以要產生change on write, 也就是分離. 所以我們需要複製這個zval.

而在php7中, 情況就變得簡單了很多, 首先在引用賦值給$ref(line 2)的時候, 生成乙個is_refernce型別, 然後因為此時有倆個變數引用它所以zend_reference這個結構的引用計數zval.value.ref->gc.refcount為2.

再隨後的賦值給$copy(line 3)的時候, 發現$val是乙個引用, 於是讓$copy指向的是zval.value.ref->val, 也就是字串值為laruence的zval, 然後把zval的引用計數+1, 也就是zval.value.ref->val.value.str.gc.refcount為2. 並沒有產生複製.

從而這就很好的解決了上一章所說的php5的那個經典的問題, 比如我們在php7下執行上一章的那個問題, 我們得到的結果是:

$ php-7.0/sapi/cli/php /tmp/1.php

used 0.00021380008539

used 0.00020173048281

可見確實沒有發生複製, 從而不會產生任何的效能問題.

對php後端技術,對php架構技術感興趣的朋友,我的官方群1023755567點選此處,一起學習,相互討論。

深入理解PHP7核心之OBJECT

今天我來講講object 物件 的一些變化。php5中,物件的定義如下 typedef struct zend object zend object 其中ce儲存了這個物件所屬的類,關於properties table和properties,properties table是申明的屬性,proper...

深入理解php核心

第二章 使用者 的執行 第三節 zend引擎與指令碼執行 第四節 小結 第三章 變數及資料型別 第二節 常量 第三節 預定義變數 第四節 靜態變數 第五節 型別提示的實現 第六節 變數的生命週期 第七節 資料型別轉換 第八節 小結 第四章 函式的實現 第二節 函式的定義,引數及返回值 第三節 函式的...

深入理解php核心

第二章 使用者 的執行 第三節 zend引擎與指令碼執行 第四節 小結 第三章 變數及資料型別 第二節 常量 第三節 預定義變數 第四節 靜態變數 第五節 型別提示的實現 第六節 變數的生命週期 第七節 資料型別轉換 第八節 小結 第四章 函式的實現 第二節 函式的定義,引數及返回值 第三節 函式的...