摘要:變量的分離和引用今天看了一下鳥哥博客變量的分離和引用的內(nèi)容就做了一個筆記如果我們我們創(chuàng)建一個變量就分配一次內(nèi)存那么像上邊的代碼那么就會造成內(nèi)存的極大浪費中的變量是一個指向的符號那么我們就可以在中來優(yōu)化上邊的代碼的中有一個字段用來記錄當前被引
PHP 變量的分離和引用
今天看了一下鳥哥博客變量的分離和引用的內(nèi)容, 就做了一個筆記!
$var = "I have a dream"; $var2 = $var; $var3 = $var;
如果我們我們創(chuàng)建一個變量就分配一次內(nèi)存, 那么像上邊的代碼,那么就會造成內(nèi)存的極大浪費. php中的變量是一個指向zval的符號, 那么我們就可以在zval中來優(yōu)化上邊的代碼!
php的zval中有一個recount字段, 用來記錄當前zval被引用的次數(shù)
$var = "abc"; //refcount = 1 $varCopy = $var; //refcount = 2
創(chuàng)建第一個變量$var時refcount的值為1, 當創(chuàng)建第二個變量$varCopy時, refcount的值為2.我們怎么能查看到這個值呢, 可以通過php提供的debug_zval_dump輸出變量的內(nèi)容和refcount
$var = "abc"; //refcount = 1 debug_zval_dump($var); //string(3) "abc" refcount(2) $varCopy = $var; //refcount = 2 debug_zval_dump($var); //string(3) "abc" refcount(3)
為什么打印的結(jié)果和我們預(yù)想的結(jié)果不一致呢, 函數(shù)debug_zval_dump有一個值傳遞的形參, 就相當于又執(zhí)行了一次$arg = $var, 執(zhí)行這段代碼的時候$var的refcount又增加了1,所以在debug_zval_dump內(nèi)部打印的結(jié)果就比實際的要大1.如果我們對一個變量進行unset那么會是一種什么樣的效果呢
$var = "abc"; $varCopy = $var; unset($var); debug_zval_dump($varCopy); //string(3) "abc" refcount(2)
如果像下邊這段代碼會發(fā)生什么呢:
$var = "abc"; $varCopy = $var; $var = 1;
如果一個變量被重新賦值, 在賦值的過程中會首先檢測refcount的值, 如果refcount大于1, php就會執(zhí)行一個分離過程.上邊的代碼在執(zhí)行到第三行的時候, php發(fā)現(xiàn)$var指向的zval的refcount大于1, 那么php就會復(fù)制一個新的zval出來, 將原來的zval的refcount減1,并修改變量符號表, 是$var指向新的zval結(jié)構(gòu) 1.這樣原來的$var和$varCopy就各自指向了不同的結(jié)構(gòu). 這個就是
copy one write 也叫寫時復(fù)制
如果我們再加上引用的情況, 那么整個過程就會更加復(fù)雜!
$var = "abc"; $varRef = &$var; $varRef = 1;
最終$var的結(jié)果是1, 這個過程被稱為
change on write 寫時改變
這次的復(fù)制是不需要進行變量分離的,需要用到zval的is_ref字段, 對于上邊的代碼, 當?shù)诙袌?zhí)行以后, $var所代表的zval的refcount變?yōu)?, 同時設(shè)置is_ref為1.
第三行的時候, php會首先檢查$varRef的zval的is_ref字段,如果為1, 則不分離.
$var = "abc"; $varCopy = $var; $varRef = &$var;
上邊的情況, 存在copy on write 同時也有change on write, 是怎么運作的呢.
當執(zhí)行第二行的時候和前邊的copy on write一樣, $var和$varCopy指向相同的zval,refcount為2
當執(zhí)行第三行的時候, php發(fā)現(xiàn)要操作的zval($var所指向的zval)的refcount大于1, php就會執(zhí)行分離操作, 把$varCopy分離出去, 并將$var和$varRef做change on write關(guān)聯(lián), 也就是refcount=2, is_ref=1
如果整個過程反過來2
$var = "abc"; //refcount=1, is_ref=0 $varRef = &$var; //refcount=2, is_ref=1 $varCopy = $var; //refcont=1, is_ref=0
第三行代碼, 因為上邊的變量$var對應(yīng)的zval有is_ref的存在, 那么當前的變量就會直接復(fù)制一份出來, 而不會觸發(fā)copy on write機制.
我們在看一段代碼
$var = "abc"; $varRef = &$var; debug_zval_dump($var); //string(3) "abc" refcount(1)
這個結(jié)果和預(yù)想的又有所差別, 是什么原因的? debug_zval_dump() 需要一個值傳遞的形參, 那么執(zhí)行debug_zval_dump($var)的時候就相當于debug_zval_dump($arg = $var) 這樣就會造成變量的分離,在debug_zval_dump($arg)就相當于對一個全新的變量執(zhí)行!
這個地方按我的理解應(yīng)該是要全新生成一個zval, 然后修改原來的zval的refcount ?
這個是我自己猜想的, 不知道是否正確.請輸入代碼 ?
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/21216.html
摘要:引用計數(shù)變量分離寫時拷貝我們一步步來理解語言特性是腳本語言,所謂腳本語言,就是說并不是獨立運行的,要運行代碼需要解析器,用戶編寫的代碼最終都會被解析器解析執(zhí)行的執(zhí)行是通過引擎,是用編寫的用戶編寫的代碼最終都會被翻譯成的虛擬機的虛擬指令來執(zhí)行 zval、引用計數(shù)、變量分離、寫時拷貝我們一步步來理解1、php語言特性PHP是腳本語言,所謂腳本語言,就是說PHP并不是獨立運行的,要運行PHP...
摘要:體現(xiàn)了業(yè)務(wù)與顯示的分離,盡量分離。就負責判斷條件,并取出數(shù)據(jù)來。顯示的工作盡量靠前頁面緩存緩存,重要概念。減輕了數(shù)據(jù)庫的壓力。控制局部不緩存在標簽中控制,該標簽不緩存。模板調(diào)用特殊方法使用對象注冊的方式來解決。文件命名函數(shù)名定 模板 數(shù)據(jù)與表現(xiàn)層的標簽分離 smarty是PHP 與 HTML代碼的分離 小型模板類 $smarty 的工作流程: 把需要顯示的全局變量,賦值塞到對象內(nèi)部的...
摘要:執(zhí)行原理是一門應(yīng)用非常簡單,開發(fā)效率極高的一門語言,其弱類型的變量能省去程序員大量的定義變量類型轉(zhuǎn)換等的時間和精力。程序最終被翻譯為一組處理函數(shù)的順序執(zhí)行。只有減為時才會真正執(zhí)行銷毀操作。 PHP執(zhí)行原理 php是一門應(yīng)用非常簡單,開發(fā)效率極高的一門語言,其弱類型的變量能省去程序員大量的定義變量、類型轉(zhuǎn)換等的時間和精力。它是一種適用于web開發(fā)的動態(tài)語言。 1. php設(shè)計的原理和特點...
摘要:支持字符串哈希列表集合有序集合等數(shù)據(jù)結(jié)構(gòu),目前不支持事務(wù)。是多入口以下關(guān)于表驅(qū)動法的描述,錯誤的是表驅(qū)動法可以作為復(fù)雜繼承結(jié)構(gòu)的替代方案,難點在于一個經(jīng)過深思熟慮的查詢表。表驅(qū)動法查找無規(guī)則分布的數(shù)據(jù)采用階梯訪問的方法最佳。 1、有關(guān)PHP字符串的說法,不對的是: CA、如果一個腳本的編碼是ISO-8859-1,則其中的字符串也會被編碼為 ISO-8859-1。B、PHP的字符串在內(nèi)部...
閱讀 3024·2021-09-22 14:59
閱讀 1864·2021-09-22 10:02
閱讀 2108·2021-09-04 16:48
閱讀 2260·2019-08-30 15:53
閱讀 2967·2019-08-30 11:27
閱讀 3403·2019-08-29 18:35
閱讀 961·2019-08-29 17:07
閱讀 2669·2019-08-29 13:27