PHP強(qiáng)化之06 - 變量的引用機(jī)制

----- 最近更新時(shí)間【2021-12-15】-----

PHP強(qiáng)化系列--目錄

本節(jié)目錄預(yù)覽:
》一先匪、概念
》二重斑、變量的存儲(chǔ)方式
》三尘执、變量的引用機(jī)制
》四絮姆、從zval變量容器底層去了解引用
》五隆箩、unset與引用
》六、對(duì)象與引用
》七阀湿、測(cè)試題
》八、參考文獻(xiàn)

一幢尚、概念

在PHP中引用意味著用不同的名字訪問(wèn)同一個(gè)變量?jī)?nèi)容。

定義方式:使用&符號(hào)

二翅楼、變量的存儲(chǔ)方式

在講解變量的引用之前尉剩,我們先來(lái)了解一下變量的存儲(chǔ)方式。

下面以一個(gè)例子來(lái)說(shuō)明:

// 1毅臊、定義一個(gè)變量$a
$a = '111';   //當(dāng)我們定義一個(gè)變量$a時(shí)理茎,那么程序就會(huì)為它在內(nèi)存當(dāng)中開(kāi)啟一個(gè)內(nèi)存空間,此時(shí)$a就指向這個(gè)內(nèi)存空間(內(nèi)存空間里存儲(chǔ)著相應(yīng)的值)管嬉。

// 2皂林、定義一個(gè)變量$b,然后將$a的值賦值給$b
$b = $a;      //這時(shí)程序不會(huì)為變量$b再開(kāi)啟一個(gè)內(nèi)存空間蚯撩,這里涉及到了php的COW機(jī)制础倍。

//只有對(duì)$a或$b中的其中一個(gè)進(jìn)行修改時(shí),才會(huì)進(jìn)行復(fù)制一份內(nèi)存胎挎。
//3沟启、修改$a
$a = '222';    //復(fù)制一份內(nèi)存,用于存儲(chǔ)修改后的值犹菇。

附:COW(copy on write)是內(nèi)存優(yōu)化的常見(jiàn)手段德迹,在php中也采用了這種方式來(lái)優(yōu)化內(nèi)存。COW:寫(xiě)時(shí)復(fù)制揭芍,即只有當(dāng)對(duì)其中一個(gè)或多個(gè)變量進(jìn)行寫(xiě)操作的時(shí)候胳搞,才會(huì)復(fù)制一份內(nèi)存,對(duì)其內(nèi)容進(jìn)行修改沼沈。

驗(yàn)證:
php有個(gè)函數(shù)memory_get_usage()可以用來(lái)查看PHP所使用的內(nèi)存情況流酬。

驗(yàn)證內(nèi)存變化

如上圖可以看出,前面兩個(gè)打印出來(lái)的內(nèi)存使用情況相差并不大列另,而第三個(gè)則拉開(kāi)了很大的差距芽腾,這是因?yàn)楫?dāng)修改變量$a時(shí),程序?yàn)樽兞?a復(fù)制了一份內(nèi)存用于存儲(chǔ)修改后的值页衙。

三摊滔、變量的引用機(jī)制

我們接著上面的例子,把$b = $a改為$b = &$a店乐,結(jié)果分析如下:

從上面可以看出艰躺,三個(gè)打印出來(lái)的內(nèi)存使用情況差別都不大,這就是引用的機(jī)制眨八。上面的情況無(wú)論你是修改$a還是$b腺兴,最后$a和$b都會(huì)變?yōu)樾薷暮蟮闹担绦虿](méi)有為修改后的變量開(kāi)啟新的內(nèi)存空間廉侧。

四页响、從zval變量容器底層去了解引用

眾所周知php的變量都是通過(guò)zend引擎來(lái)處理的篓足,而zval結(jié)構(gòu)體則是管理我們變量的一個(gè)容器,而xdebug_debug_zval函數(shù)則是我們調(diào)試zval結(jié)構(gòu)體的一個(gè)好工具(注意闰蚕,想使用該函數(shù)需要安裝Xdebug插件)栈拖。

使用函數(shù)xdebug_debug_zval()打印出來(lái)的zval結(jié)構(gòu)如下:

<?php
$a = 'aaa';
xdebug_debug_zval('a');

在瀏覽器輸出如下內(nèi)容:

a:
(refcount=1, is_ref=0)string 'aaa' (length=3)

結(jié)構(gòu)說(shuō)明:
1)refcount表示引用計(jì)數(shù),用來(lái)記錄有多少個(gè)變量指向這個(gè)zval容器没陡;
2)is_ref表示是否為引用涩哟,一個(gè)bool型的值;
3)表示數(shù)據(jù)的類(lèi)型盼玄;
4)最后則為它的值贴彼。
注意:當(dāng)refcount為1的時(shí)候,is_ref必須為0强岸。當(dāng)refcount為0的時(shí)候锻弓,該容器會(huì)被刪除掉,釋放空間出來(lái)蝌箍。

沒(méi)有引用
使用引用

如果沒(méi)有安裝Xdebug插件青灼,也可以使用php內(nèi)置函數(shù)debug_zval_dump來(lái)查看refcount的值,不過(guò)看不了其它的妓盲。

五杂拨、unset與引用

當(dāng)一個(gè)變量是使用了引用時(shí),unset函數(shù)只會(huì)刪除引用悯衬,并不會(huì)銷(xiāo)毀內(nèi)存空間弹沽。

由如下分析可以證明:

從上面可以看出,三次打印出來(lái)的內(nèi)存使用情況基本沒(méi)有什么變動(dòng)筋粗。

六策橘、對(duì)象與引用

在PHP中,對(duì)象本身就是引用傳遞娜亿。

驗(yàn)證如下:

分析:

1)當(dāng)定義$a2 = $a1時(shí)丽已,zval結(jié)構(gòu)體的refcount值由1變?yōu)?;
2)此時(shí)無(wú)論修改的是$a2->type還是$a1->type的值买决,其實(shí)修改的都是同時(shí)一個(gè)空間里的值沛婴;
3)由此可以發(fā)現(xiàn)此時(shí)并沒(méi)有使用到COW機(jī)制;
4)這是因?yàn)檫@種情況下$a1和$a2引用到了同一個(gè)對(duì)象督赤。

七嘁灯、測(cè)試題

1、寫(xiě)出如下程序的輸出結(jié)果

test = 'aaaaaa';
$abc = & $test;
unset($test);
echo $abc;
// 結(jié)果:aaaaaa

2躲舌、寫(xiě)出如下程序的輸出結(jié)果

$data = ['a', 'b', 'c'];
foreach($data as $k => $v){
        $v = &$data[$k];
        var_dump($data);
}
var_dump($data);
//程序運(yùn)行時(shí)丑婿,每一次循環(huán)結(jié)束后變量$data的值是什么?
//程序執(zhí)行完后,變量$data的值是什么羹奉?
//請(qǐng)解釋

運(yùn)行結(jié)果如下:

八毅贮、參考文獻(xiàn)

1、Xdebug
官方手冊(cè):https://xdebug.org/docs/all

2尘奏、垃圾回收機(jī)制
關(guān)于PHP垃圾回收機(jī)制(Garbage Collection . GC),這位作者寫(xiě)了三篇比較好的文章病蛉,其中第一篇主要就是講解PHP如何處理變量的炫加。
1) Collecting Garbage: PHP's take on variables
2)Collecting Garbage: Cleaning Up
3)Collecting Garbage: Performance Considerations
第一篇的譯文: https://blog.csdn.net/newbird105/article/details/45315429

3、關(guān)于COW
1)CSDN博客文章:php中COW機(jī)制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末铺然,一起剝皮案震驚了整個(gè)濱河市俗孝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌魄健,老刑警劉巖赋铝,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異沽瘦,居然都是意外死亡革骨,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)析恋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)良哲,“玉大人,你說(shuō)我怎么就攤上這事助隧≈欤” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵并村,是天一觀的道長(zhǎng)巍实。 經(jīng)常有香客問(wèn)我,道長(zhǎng)哩牍,這世上最難降的妖魔是什么棚潦? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮姐叁,結(jié)果婚禮上瓦盛,老公的妹妹穿的比我還像新娘。我一直安慰自己外潜,他們只是感情好原环,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著处窥,像睡著了一般嘱吗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,258評(píng)論 1 300
  • 那天谒麦,我揣著相機(jī)與錄音俄讹,去河邊找鬼。 笑死绕德,一個(gè)胖子當(dāng)著我的面吹牛患膛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耻蛇,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼踪蹬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了臣咖?” 一聲冷哼從身側(cè)響起跃捣,我...
    開(kāi)封第一講書(shū)人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎夺蛇,沒(méi)想到半個(gè)月后疚漆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡刁赦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年娶聘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片截型。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡趴荸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宦焦,到底是詐尸還是另有隱情发钝,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布波闹,位于F島的核電站酝豪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏精堕。R本人自食惡果不足惜孵淘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望歹篓。 院中可真熱鬧瘫证,春花似錦、人聲如沸庄撮。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)洞斯。三九已至毡庆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背么抗。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工毅否, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蝇刀。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓螟加,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親吞琐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仰迁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354