PHP——4(PHP賦值行為)

PHP——2(PHP變量作用域)
PHP——3(PHP變量分離/引用(Variables Separation))
為輔助閱讀熬甫,可直接跳過

Laruence關(guān)于引用賦值行為的描述和用debug_zval_dump刺探的結(jié)果有出入栖秕,下面我會指出Laruence的敘述有誤的地方邢笙。
總結(jié)來說,分析PHP賦值行為遵循以下原則:
在保證常規(guī)賦值思維的前提下墅拭,保證占用盡量小的內(nèi)存和做盡量少的指針指向變化秒咐。

1.內(nèi)存的問題("Copy on write")
由于PHP弱類型變量的原因,在PHP中存儲一個變量會比在C等強(qiáng)類型語言中占用的內(nèi)存大得多宿亡,如果也按照C語言中每個變量開辟一個單獨(dú)的內(nèi)存空間來保存,顯然將占用大量的內(nèi)存空間纳令,顯然這并不是最優(yōu)化的設(shè)計挽荠。我們自己可以設(shè)想一下在PHP中諸如以下的賦值語句

<?php  
$a=1;  
$b=$a;  
?>  

對$a顯然要開辟一塊新的內(nèi)存克胳,但是對于$b來說要不要開辟新的內(nèi)存呢?
顯然圈匆,在PHP中我們是不需要像C一樣毯欣,每次都去開辟變量內(nèi)存的,針對上面的情況臭脓,我們只需要在變量符號表中加入名字b,同時將其對應(yīng)的zval指針指向$a指向的zval內(nèi)存地址即可腹忽。其內(nèi)存結(jié)構(gòu)變化示意圖如下

image.png

這時候沒有做內(nèi)存開辟来累,那么什么時候會做內(nèi)存開辟呢?答案是出現(xiàn)不可調(diào)和的矛盾時會產(chǎn)生內(nèi)存開辟窘奏。
我們觀察“$a賦值X”這一語句嘹锁,賦值可為普通賦值(=)和引用賦值(=&),X可為常量或變量着裹。所有的內(nèi)存開辟都是在X端完成领猾,整理列表如下。

image.png

可以看到骇扇,新建內(nèi)存只有如下三種情況:

  1. 名字a不存在摔竿,賦給一個常量,這時候沒辦法必須新建
  2. $b=&$c少孝,$a=$b继低,最開始$b和$c捆綁在一起,除非$b重新綁定到其他引用關(guān)系上稍走,$b袁翁、$c的綁定關(guān)系是不會解除的,這時候$a想和$b在一起又不想和$c綁定(如果$a=&$b婿脸,那就是a粱胜、b、c綁定了)狐树,那就只有分出去一個$b的復(fù)制品給$a了焙压,希望這樣解釋比較好理解。在程序中判斷條件為賦值行為為=且X的is_ref=1抑钟。
  3. $b=$c,$a=&$b冗恨,這時候$b想和$a綁定在一起,$a又不想$c攙和進(jìn)來(如果$b=&$c味赃,那就是a掀抹、b、c綁定了)心俗,那就只有為難$b分出個復(fù)制品給$c了傲武。在程序中判斷條件為賦值行為為=&且X的refcount>1蓉驹。
    可以看到所有要新建內(nèi)存的地方都是矛盾不可調(diào)和的地方,這也是動態(tài)類型語言設(shè)計的高明之處揪利,也是所謂的"Copy on write"原則的意思态兴。

2.指針的問題("Change on write")
在之前我們談到的$a,$b指向同一內(nèi)存結(jié)構(gòu),實際上就是$a,$b名字對應(yīng)的指針指向統(tǒng)一內(nèi)存結(jié)構(gòu)疟位,對于如下語句

<?php  
$a = 1;  
$b = $a;  
echo '$a='.$a."\t".'$b='.$b."\n";  
$b = 2;  
echo '$a='.$a."\t".'$b='.$b."\n";  
  
$c = 1;  
$d = &$c;  
echo '$c='.$c."\t".'$d='.$d."\n";  
$d = 2;  
echo '$c='.$c."\t".'$d='.$d."\n";  
?>  

$a=1 $b=1
$a=1 $b=2
$c=1 $d=1
$c=2 $d=2

這里我們用一張圖來說明其內(nèi)存結(jié)構(gòu)和指針指向變化示意圖如下


image.png

這兩個例子的唯一不同在于定義$d時加上了一個引用定義符&瞻润。
為什么$b賦值時指向發(fā)生了變化而$d賦值時沒有變化,是么時候指針指向才會發(fā)生變化呢?答案是同樣是出現(xiàn)不可調(diào)和的矛盾時會產(chǎn)生指針指向改變甜刻。
同樣我們觀察“$a賦值X”這一語句绍撞,賦值可為普通賦值(=)和引用賦值(=&),X可為常量或變量得院。所有的指針指向改變都是在$a端完成傻铣。
這里我就不再列表了,可以同樣按照以上方法分析祥绞,結(jié)論同樣是三種情況下指針指向發(fā)生改變:

  1. 名字a不存在非洲,這時候新建了名字沒辦法必須將指針指向一個地方
  2. $b=1,$a=$b蜕径,$a=2两踏,最開始$a和$b指向同一內(nèi)存結(jié)構(gòu),當(dāng)$a要指向一個新的值又不希望$c指向這個值兜喻,那么只有將$a指針從原來的指向$b內(nèi)存結(jié)構(gòu)改為指向新建的內(nèi)存結(jié)構(gòu)缆瓣。在程序中判斷條件為賦值行為為=且$a的refcount>1。
  3. $b=1虹统,$c=2弓坞,$a=&$b,$a=&$c车荔,這時候$a想和$c綁定在一起渡冻,只能綁定一個內(nèi)存結(jié)構(gòu),$a只有舍棄$b忧便,將$a的指針從原來指向$b內(nèi)存結(jié)構(gòu)改為指向$c內(nèi)存結(jié)構(gòu)族吻。在程序中判斷條件為賦值行為為=&且$a的is_ref=1。
    可以看到所有要改變指針指向的地方同樣是矛盾不可調(diào)和的地方珠增,這同樣也是動態(tài)類型語言設(shè)計的高明之處超歌,也是所謂的"Change on write"原則的意思。

實際上所有弱類型的語言機(jī)理大概都是如此蒂教,只有按照這樣的邏輯來設(shè)計的動態(tài)語言才是最優(yōu)性能同時不反人類的巍举,下一節(jié)深入到PHP的存儲結(jié)構(gòu)來講解PHP的引用,說明PHP引用特別是對象引用容易被錯誤理解的地方凝垛。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末懊悯,一起剝皮案震驚了整個濱河市蜓谋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌炭分,老刑警劉巖桃焕,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異捧毛,居然都是意外死亡观堂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進(jìn)店門呀忧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來师痕,“玉大人,你說我怎么就攤上這事荐虐。” “怎么了丸凭?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵福扬,是天一觀的道長。 經(jīng)常有香客問我惜犀,道長铛碑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任虽界,我火速辦了婚禮汽烦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘莉御。我一直安慰自己撇吞,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布礁叔。 她就那樣靜靜地躺著牍颈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪琅关。 梳的紋絲不亂的頭發(fā)上煮岁,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天,我揣著相機(jī)與錄音涣易,去河邊找鬼画机。 笑死,一個胖子當(dāng)著我的面吹牛新症,可吹牛的內(nèi)容都是我干的步氏。 我是一名探鬼主播,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼徒爹,長吁一口氣:“原來是場噩夢啊……” “哼戳护!你這毒婦竟也來了金抡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤腌且,失蹤者是張志新(化名)和其女友劉穎梗肝,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铺董,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡巫击,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了精续。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坝锰。...
    茶點故事閱讀 40,928評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖重付,靈堂內(nèi)的尸體忽然破棺而出顷级,到底是詐尸還是另有隱情,我是刑警寧澤确垫,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布弓颈,位于F島的核電站,受9級特大地震影響删掀,放射性物質(zhì)發(fā)生泄漏翔冀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一披泪、第九天 我趴在偏房一處隱蔽的房頂上張望纤子。 院中可真熱鬧,春花似錦款票、人聲如沸控硼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽象颖。三九已至,卻和暖如春姆钉,著一層夾襖步出監(jiān)牢的瞬間说订,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工潮瓶, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留陶冷,地道東北人。 一個月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓毯辅,卻偏偏與公主長得像埂伦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子思恐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,937評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型沾谜。 運(yùn)用指針編程是C語言最主要的風(fēng)格之一膊毁。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); ...
    朱森閱讀 3,452評論 3 44
  • ———————————————回答好下面的足夠了---------------------------------...
    恒愛DE問候閱讀 1,720評論 0 4
  • 多線程基跑、特別是NSOperation 和 GCD 的內(nèi)部原理婚温。運(yùn)行時機(jī)制的原理和運(yùn)用場景。SDWebImage的原...
    LZM輪回閱讀 2,010評論 0 12
  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛閱讀 1,990評論 0 7
  • 開篇 本文章閱讀用時15分鐘媳否,屬于C#零基礎(chǔ)入門的教程栅螟。 建議按照文章項目進(jìn)行實戰(zhàn),多寫代碼篱竭,多聯(lián)系力图。 這是小白學(xué)...
    做全棧攻城獅閱讀 1,747評論 0 6