底層剖析引用實現原理(引用是占有記憶體空間的)

2021-10-10 16:31:31 字數 2023 閱讀 8143

正如《c++ primer》中所述,「引用即別名,它並非物件,相反地,它只是乙個已經存在的物件所起的另外乙個名字。」剛學習c++的時候,覺得引用就是乙個別名,並不會占有記憶體。剖析了引用的底層實現原理之後,才發現這是錯誤的,引用也是會占有記憶體的,且底層是通過指標來實現的。

以下是一段對引用和源變數取位址的**,一起看一下

#

include

using

namespace std;

intmain()

執行結果:

我們發現,a和b的位址是一樣的,看來引用是不占用記憶體的。實際上,&b並不能得到b的位址,而得到的還是變數a的位址。原因就是,引用在c++中是通過乙個常指標來實現的,即&b=a實際上等價於int* const b=&a,而編譯器會把&b編譯為:&(*b),那麼得到的自然就是a的位址,所以我們會看到&a、&b得到的位址是一樣的。但是一定要注意,&b並不是b的位址。

為了佐證上述原因,我們在上述**中加入乙個常指標int* const c=&a,即:

int a =10;

int&b = a;

int*

const c =

&a;

利用vs2013編譯器將源**轉換為反彙編,則引用b和常指標c實現的反組合語言如下:

//int a = 10;  //源**

01305e88 mov dword ptr [a]

,0ah //將10複製到變數a的位址空間

//int &b = a; //源**

01305e8f lea eax,

[a]//將變數a的位址複製到暫存器eax中

01305e92 mov dword ptr [b]

,eax //從暫存器eax中取出位址賦值給變數b的位址空間

//int* const c = &a; //源**

01305e95 lea eax,

[a]//將變數a的位址複製到暫存器eax中

01305e98 mov dword ptr [c]

,eax //從暫存器eax中取出位址賦值給變數c的位址空間

從組合語言可以看到,源**int &b = a和int* const c = &a的彙編**是一模一樣的,均為:將變數a的位址複製到暫存器eax中,再將eax中的值賦值給變數b或者c。這也證明了:引用是通過常指標來實現的。那麼,為什麼是常指標而不是普通指標呢?因為引用的物件是不能改變的,若為普通指標則可以改變指向的物件,但用常指標實現就能保證指向的物件是不變的。但是,我們會發現由於編譯器改變了引用的取位址含義,那麼想獲取引用的真實位址好像就很難了,我們能看到的自然只有與引用物件相同的位址。

通過上面的分析,希望讀者能更正乙個認識:引用同指標一樣占有記憶體空間的,且記憶體的大小與指標一樣,即32系統上是4個位元組,64位系統上是8個位元組。但是對引用進行sizeof運算得到的是被引用物件的記憶體大小,並不是其真實所佔記憶體這一點非常重要,很多人寫的部落格都說「引用不佔記憶體」,這是錯誤的。

分析了引用的底層實現原理之後,引用與指標的區別也就一目了然了,下面就總結一下。

安全性:引用的物件不能改變,安全性好;但指標指向的物件是可以改變的,不能保證安全性。

方便性:引用實際上是封裝好的指標解引用(即b->*b),可以直接使用;但指標需要手動解引用,使用更麻煩;

級數:引用只有一級,不能多次引用;但指標的級數沒有限制。

初始化:引用必須被初始化為乙個已有物件的引用,而指標可以初始化為null。

c 中「引用」的底層實現原理詳解

c 中 引用 的底層實現原理詳解 c c lws123253的部落格 csdn部落格 目錄 初學c 中的 引用 這一概念的時候,很多人都是懵的,大家大概都會產生這樣的疑問?什麼是引用?引用占用記憶體嗎?於是,為了驗證你的猜想,你可能會寫出下面這樣的 來驗證 includeusing namespac...

c 引用極其底層實現

一 c 中引用的語法是這樣的 int x 100 int x x 它的意思就是是給變數x起了乙個別名,在以後的 中,x其實就是x,這兩個是等價的。舉個例子,在 唐伯虎點秋香 中,唐伯虎叫做華安,又叫做9527,其實這三個名字都是同乙個人,引用就是這個意思。注意事項 引用初始化的時候一定要繫結乙個變數...

C C 中引用的底層原理

其實我們見到的大部分解釋都是這麼說的 首先我們來看看對引用取位址會發生什麼?include intmain 結果輸出如下 e99a7dec e99a7dec可以看到,對引用取位址其實就是對被引用物件取位址,所以這樣肯定行不通。但是,我們可以通過位址偏移來間接實現。include class test...