C++中的引用推導(dǎo)

導(dǎo)讀

  • 為什么說引用是別名
  • 為什么引用作為形參可以修改實參的值
  • 為什么引用初始化后無法指向其他對象
  • 引用與指針對應(yīng)的匯編代碼
  • 對引用的理解

為什么說引用是別名

int main() {
    int a = 10;
    int &b = a;
    b = 20;
    return 0;
}
1-1

從地址的角度來說,a與b兩者的內(nèi)存地址相同,都存儲著0x14這個數(shù)值,所以b可以理解為a的別名。既然引用是別名,顯然需要通過某個變量初始化,因此引用必須在定義的時候直接通過某個變量初始化。

為什么引用作為形參可以修改實參的值

void test(int &x) {
    x = 99;
}

int main() {
    int a = 10;
    test(a);
    return 0;
}
2-1
2-2

在調(diào)用函數(shù)前,將a的地址存入rdi中,此時可以通過rdi存儲的地址值來對變量a進(jìn)行讀寫操作。

2-3

進(jìn)入函數(shù)后,向rdi存儲的內(nèi)存地址中寫入0x63數(shù)據(jù),即十進(jìn)制的99。由于rdi中存儲的是變量a的內(nèi)存地址,所以此時a的值等于99。

為什么引用初始化后無法指向其他對象

例子中的注釋對應(yīng)著匯編代碼:

int main() {
//    movl   $0xa, -0x8(%rbp)
    int a = 10;
    
//    leaq   -0x8(%rbp), %rcx
//    movq   %rcx, -0x10(%rbp)
//    movq   -0x10(%rbp), %rcx
    int &x = a;
    
//    movl   $0x14, (%rcx)
    x = 20;
    
//    movl   $0x63, -0x14(%rbp)
    int b = 99;

    return 0;
}

可以看到,在對引用賦值時,轉(zhuǎn)成匯編對應(yīng)的是通過寄存器賦值,中間通過movq %rcx, -0x10(%rbp)轉(zhuǎn)存了一下a的內(nèi)存地址。那么,是否可以通過-0x10(%rbp)這個內(nèi)存地址來修改x的指向?

3-1

可見,當(dāng)我們向-0x10(%rbp)內(nèi)存地址中寫入變量b的內(nèi)存地址時,引用x的值變成了變量b的值99。雖然可以通過lldb修改引用的指向,但在C++層面很難得知引用的內(nèi)存地址(即使通過代碼中變量存儲地址推導(dǎo)出引用地址,同樣需要直接操作內(nèi)存地址,因為沒有一個變量名代表這個內(nèi)存地址)。

當(dāng)對引用使用&符號時,得到的是變量a的地址,而非引用的地址(請參考為什么說引用是別名這一小節(jié))。

是否可以通過直接修改&引用的值,來達(dá)到改變引用指向?

3-2

很遺憾,&x無法賦值,因為&x等于變量a的地址,而a的地址是個常量,常量不能是左值。

引用與指針對應(yīng)的匯編代碼

int main() {
//    movl   $0xa, -0x8(%rbp)
    int a = 10;
    
//    leaq   -0x8(%rbp), %rcx
    
//    movq   %rcx, -0x10(%rbp)
    int &x = a;
    
//    movq   %rcx, -0x18(%rbp)
    int *p = &a;
    return 0;
}

從匯編代碼來看,無法區(qū)分是在操作引用還是在操作指針,兩者的區(qū)別僅在于可以通過&p獲取指針的地址,從而改變指針變量p的指向,但是無法通過&x獲取引用的地址(獲取到的是a的地址)。

對引用的理解

文章開頭已經(jīng)說過,可以把引用理解為變量的別名。但是通過為什么引用初始化后無法指向其他對象這一小節(jié)可以看到,引用其實也是需要開辟內(nèi)存的,只是內(nèi)存地址沒有對應(yīng)的變量名,在這個內(nèi)存地址中存儲著引用的變量的內(nèi)存地址,可以把這塊因為引用而開辟的匿名內(nèi)存地址理解為二級指針。
此處可以類比指針,指針存儲著某個變量的地址,但是同樣有一塊空間存儲著指針,而這塊存儲著指針的內(nèi)存空間就是&指針,即指針的地址,引用其實就是個匿名指針。


Have fun!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文地址:https://niyaoyao.github.io/2016/07/29/Objective-C-Ru...
    mengjz閱讀 595評論 0 0
  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型。 運(yùn)用指針編程是C語言最主要的風(fēng)格之一。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); ...
    朱森閱讀 3,619評論 3 44
  • 指針 在了解什么是指針之前,我們需要先搞清楚數(shù)據(jù)在內(nèi)存中是如何存儲的,又是如何讀取的。 如果在程序中定義一個變量,...
    Longshihua閱讀 1,163評論 0 4
  • 幾種語言的特性 匯編程序:將匯編語言源程序翻譯成目標(biāo)程序編譯程序:將高級語言源程序翻譯成目標(biāo)程序解釋程序:將高級語...
    囊螢映雪的螢閱讀 3,066評論 1 5
  • 指針和引用形式上很好區(qū)別,但是他們似乎有相同的功能,都能夠直接引用對象,對其進(jìn)行直接的操作。但是什么時候使用指針?...
    代碼人生ll閱讀 476評論 0 0

友情鏈接更多精彩內(nèi)容