正如《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...