C++ 引用占用內(nèi)存育灸?

一、引用的本質(zhì)是什么

說到引用昵宇,一般C++的教材中都是這么定義的:

1磅崭,引用就是一個(gè)對(duì)象的別名。

2瓦哎,引用不是值不占內(nèi)存空間砸喻。

3,引用必須在定義時(shí)賦值蒋譬,將變量與引用綁定割岛。

那你有沒有想過,上面的定義正確嗎犯助?編譯器是如何解釋引用的癣漆?

這里先給出引用的本質(zhì)定義,后面我們?cè)龠M(jìn)一步論證剂买。

1惠爽,引用實(shí)際是通過指針實(shí)現(xiàn)的。

2瞬哼,引用是一個(gè)常量指針婚肆。

3,引用在內(nèi)存中占4個(gè)字節(jié)坐慰。

4较性,在對(duì)引用定義時(shí),需要對(duì)這個(gè)常量指針初始化结胀。

二两残、探究本質(zhì)

我們從最簡(jiǎn)單的變量的定義開始,看編譯器會(huì)做哪些事情把跨。

int var = 42;

mov? ? ? ? dword ptr [var],2Ah? // 對(duì)應(yīng)匯編代碼

上面語句申請(qǐng)了一塊內(nèi)存空間人弓,占4個(gè)字節(jié),存放了一個(gè)int型的變量着逐。內(nèi)存里放的是42的二進(jìn)制碼崔赌。

匯編代碼向我們表達(dá)的意思就是把42寫入以var為地址的內(nèi)容區(qū)域意蛀。var有點(diǎn)像我們理解上的指針,只是編譯器并沒有把它抽象出來健芭,而是讓我們更表象的理解:申請(qǐng)一個(gè)變量县钥,它的值為42。

那么var這個(gè)變量名放在哪呢慈迈?

我們知道程序如果訪問內(nèi)存里的數(shù)據(jù)若贮,需要通過地址來進(jìn)行訪問,所以上面的代碼在經(jīng)過編譯器生成目標(biāo)代碼時(shí)痒留,用存放42的地址了所有的var谴麦,所以結(jié)論時(shí),目標(biāo)文件中不存在var伸头,所以變量名本身是不占內(nèi)存的匾效。

而我們知道,引用是變量的一個(gè)別名恤磷。那么面哼,從這很多人會(huì)聯(lián)想到,引用會(huì)不會(huì)也只是一個(gè)名字而已扫步,編譯器在生成目標(biāo)代碼的時(shí)候魔策,會(huì)用實(shí)際地址替換引用呢?

答案并非這樣河胎!

那我們接下來看看闯袒,當(dāng)我們定義一個(gè)引用時(shí),發(fā)生了什么:

1? ? int var = 42;

2 01303AC8? mov? ? ? ? dword ptr [var],2Ah?

3? ? int&? refVar = var;

4 01303ACF? lea? ? ? ? eax,[var]?

5 01303AD2? mov? ? ? ? dword ptr [refVar],eax

上面的代碼顯示仿粹,當(dāng)定義一個(gè)引用時(shí),編譯器將var的地址賦給了以refVar為地址的一塊內(nèi)存區(qū)域原茅。也就是說refVar其實(shí)存放的是var的地址吭历。

這讓我們聯(lián)想到了指針,那么我們看看定義一個(gè)指針是發(fā)生了什么:

1? ? int var = 42;

2 01213AC8? mov? ? ? ? dword ptr [var],2Ah?

3? ? int* ptrVar = &var;

4 01213ACF? lea? ? ? ? eax,[var]?

5 01213AD2? mov? ? ? ? dword ptr [ptrVar],eax

沒錯(cuò)擂橘,沒有任何差別晌区,定義一個(gè)引用和一個(gè)指針的匯編代碼完全一致!

三通贞、const哪里去了

相信從上面的分析時(shí)朗若,你可能已經(jīng)相信了,引用實(shí)際上就是一個(gè)指針昌罩。那么為什么說引用是一個(gè)常量指針呢哭懈,在目標(biāo)代碼里有什么體現(xiàn)呢?

這個(gè)問題其實(shí)要從C++底層機(jī)制談起茎用,C++為我們提供的各種存取控制僅僅是在編譯階段給我們的限制遣总,也就是說編譯器確保了你在完成任務(wù)之前的正確行為睬罗,如果你的行為不正確,那么編譯器就是給你在編譯時(shí)提示錯(cuò)誤旭斥。所謂的const和private等在實(shí)際的目標(biāo)代碼里根本不存在容达,所以在程序運(yùn)行期間只要你愿意,你可以通過內(nèi)存工具修改它的任何一個(gè)變量的值垂券。

這也就解釋了為什么上面的兩段代碼中引用和指針的匯編代碼完全一致花盐。

C++設(shè)計(jì)引用,并用常量指針來從編譯器的角度實(shí)現(xiàn)它菇爪,目標(biāo)是為了提供比指針更高的安全性算芯,因?yàn)槌A恐羔樢坏┡c變量地址綁定將不能更改,這樣降低了指針的危險(xiǎn)系數(shù)娄帖,它提供了一種一對(duì)一的指針也祠。

但是你覺得使用引用就安全了嗎?它同樣會(huì)有與使用指針一樣的問題

1 int *var = new int(42);

2 int &ref = *var;

3 delete var;

4 ref = 42;

5 return 0;

上面這段代碼就很不安全近速,因?yàn)閞ef引用的內(nèi)存區(qū)域不合法诈嘿。

為了進(jìn)一步驗(yàn)證引用與指針在本質(zhì)上的相同,我們看當(dāng)引用作為函數(shù)參數(shù)傳遞時(shí)削葱,編譯器的行為:

1 void Swap(int& v1, int& v2);

2 void Swap(int* v1, int* v2);

3

4? ? int var1 = 1;

5 00A64AF8? mov? ? ? ? dword ptr [var1],1?

6? ? int var2 = 2;

7 00A64AFF? mov? ? ? ? dword ptr [var2],2?

8? ? Swap(var1,var2);

9 00A64B06? lea? ? ? ? eax,[var2]?

10 00A64B09? push? ? ? ? eax?

11 00A64B0A? lea? ? ? ? ecx,[var1]?

12 00A64B0D? push? ? ? ? ecx?

13 00A64B0E? call? ? ? ? Swap (0A6141Fh)?

14 00A64B13? add? ? ? ? esp,8?

15? ? Swap(&var1, &var2);

16 00A64B16? lea? ? ? ? eax,[var2]?

17 00A64B19? push? ? ? ? eax?

18 00A64B1A? lea? ? ? ? ecx,[var1]?

19 00A64B1D? push? ? ? ? ecx?

20 00A64B1E? call? ? ? ? Swap (0A61424h)?

21 00A64B23? add? ? ? ? esp,8

上面代碼再次證明了奖亚,引用與指針的行為完全一致,只是編譯器在編譯時(shí)對(duì)引用作了更嚴(yán)格的限制析砸。

四昔字、引用占多大的內(nèi)存空間

因?yàn)樵谠诒磉_(dá)式中,使用引用實(shí)際上就像使用變量本身一樣首繁,所以直接用sizeof是得不到引用本身的大小的作郭。

double var = 42.0;

double& ref = var;

cout << sizeof var << endl;? // print 8

cout << sizeof ref << endl;? // print 8

我們可以通過定義一個(gè)只含有引用的類來解決這個(gè)問題:

1 class refClass{

2 private:

3? ? double& ref;

4 public:

5? ? refClass(double var = 42.0) :ref(var){}

6 };

7

8 cout << sizeof refClass << endl;? // print 4

所以結(jié)論就是引用和指針一樣實(shí)際占內(nèi)存空間4個(gè)字節(jié)。



正確結(jié)論:


不要用匯編結(jié)果來替代概念弦疮,引用不占空間意思就是不占對(duì)象空間夹攒,不表示不占指針的少量空間。實(shí)際上指針是匯編工具實(shí)現(xiàn)引用的一種方式而已胁塞,而有的優(yōu)化結(jié)果可能沒有代表自己的指針咏尝。

總而言之,引用就是引用啸罢,是這種概念编检,它為方便程序員使用,和方便匯編工具優(yōu)化而產(chǎn)生扰才。匯編怎么實(shí)現(xiàn)和優(yōu)化是匯編的事允懂,至于出了什么違反該概念的結(jié)果,是匯編的錯(cuò)衩匣,而不是定義的錯(cuò)累驮,不要本末倒置酣倾。


你可以通過匯編來了解編譯器怎樣實(shí)現(xiàn)引用

引用 卻不應(yīng)該用匯編來解釋 它只是一個(gè)概念


贊同,引用只是編譯器之上谤专,給出來的一個(gè)抽象定義躁锡。接口的實(shí)現(xiàn),由編譯器來決定置侍!


仔細(xì)想想映之,確實(shí)如此,引用只是一個(gè)概念蜡坊,為我們提供了一個(gè)接口杠输。怎么實(shí)現(xiàn),由編譯器自己決定秕衙。



原文鏈接:http://www.cnblogs.com/ronny/p/3662556.htm

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蠢甲,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子据忘,更是在濱河造成了極大的恐慌鹦牛,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勇吊,死亡現(xiàn)場(chǎng)離奇詭異曼追,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)汉规,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門礼殊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人针史,你說我怎么就攤上這事晶伦。” “怎么了啄枕?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵婚陪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我射亏,道長(zhǎng)近忙,這世上最難降的妖魔是什么竭业? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任智润,我火速辦了婚禮,結(jié)果婚禮上未辆,老公的妹妹穿的比我還像新娘窟绷。我一直安慰自己,他們只是感情好咐柜,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布兼蜈。 她就那樣靜靜地躺著攘残,像睡著了一般。 火紅的嫁衣襯著肌膚如雪为狸。 梳的紋絲不亂的頭發(fā)上歼郭,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音辐棒,去河邊找鬼病曾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛漾根,可吹牛的內(nèi)容都是我干的泰涂。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼辐怕,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼逼蒙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寄疏,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤是牢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后赁还,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妖泄,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年艘策,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蹈胡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡朋蔫,死狀恐怖罚渐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情驯妄,我是刑警寧澤荷并,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站青扔,受9級(jí)特大地震影響源织,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜微猖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一谈息、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧凛剥,春花似錦侠仇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽互亮。三九已至,卻和暖如春余素,著一層夾襖步出監(jiān)牢的瞬間豹休,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工桨吊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留慕爬,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓屏积,卻偏偏與公主長(zhǎng)得像医窿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子炊林,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

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