欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++詳細(xì)分析引用的使用及其底層原理

 更新時(shí)間:2022年04月24日 11:25:48   作者:Fengliguantou@  
引用是C++一個(gè)很重要的特性,顧名思義是某一個(gè)變量或?qū)ο蟮膭e名,對(duì)引用的操作與對(duì)其所綁定的變量或?qū)ο蟮牟僮魍耆葍r(jià),這篇文章主要給大家總結(jié)介紹了C++中引用的相關(guān)知識(shí)點(diǎn),需要的朋友可以參考下

引用

引用不是定義一個(gè)新變量,而是給已存在的變量取了一個(gè)外號(hào),編譯器不會(huì)為引用變量開辟內(nèi)存空間,它和它引用的變量共用同一塊內(nèi)存空間。

舉個(gè)形象的例子,魯智深又被叫做"花和尚",這里的花和尚和魯智深都是同一個(gè)人,花和尚就是魯智深的引用,說白了引用其實(shí)就是取外號(hào)。

引用的注意事項(xiàng)

  • 1.引用必須初始化
int main()
{
int a;
int &b =a;
}

這時(shí)b就是a的外號(hào)。
下面的這種沒有初始化的做法是錯(cuò)誤的

int main()
{
int &b;//引用必須初始化,這里沒有進(jìn)行初始化。
}
  • 2.一個(gè)變量可以有多個(gè)引用

在生活中,我們可能有多個(gè)名字,在家中父母可能叫你小名,在外面別人可能叫你的全名或者外號(hào)

其實(shí)也就是一個(gè)變量可以有多個(gè)外號(hào),也就是可以有多個(gè)引用。

int main()
{
int a;
int &b=a;
int &c=a;
}

這里的b和c都是a的外號(hào),b,c,a三個(gè)變量指向的都是同一塊內(nèi)存空間。

  • 3.引用一旦引用了一個(gè)實(shí)體就不能再引用其他的實(shí)體

形象的來說,就是你和你的親弟弟不能用同一個(gè)名字

下圖c是a的引用,那么現(xiàn)在他就不能做b的引用了。

引用做參數(shù)

在講引用做參數(shù)之前,我們先需要了解一下,參數(shù)傳值和參數(shù)傳引用的區(qū)別。

1.參數(shù)傳值

下圖實(shí)參傳遞了a,形參b對(duì)其進(jìn)行了接收并修改,但是實(shí)參a最終并沒有受到影響,這又是為什么呢?

原來,參數(shù)傳值的時(shí)候,形參會(huì)生成一份實(shí)參數(shù)據(jù)的拷貝,也就是說實(shí)參和形參指向的不是同一塊空間,所以形參的修改不會(huì)影響實(shí)參。

2.引用傳參

下圖進(jìn)行了引用傳參,形參的修改對(duì)實(shí)參產(chǎn)生了影響,我們可以大膽推測(cè)形參和實(shí)參是一塊空間。

原來,引用傳參的時(shí)候,形參不再是實(shí)參的拷貝,而是實(shí)參的一個(gè)引用,也就是說實(shí)參和形參指向的是同一塊內(nèi)存空間,形參的改變會(huì)影響實(shí)參。

實(shí)參傳值和傳引用的優(yōu)劣

1.實(shí)參傳值:

缺點(diǎn):形參會(huì)生成一份實(shí)參數(shù)據(jù)的拷貝,當(dāng)數(shù)據(jù)量很大時(shí),在一定程度上就會(huì)影響程序的運(yùn)行速度

優(yōu)點(diǎn):因?yàn)樾螀⑹菍?shí)參的拷貝,所以形參的操作不會(huì)影響實(shí)參,可以防止實(shí)參數(shù)據(jù)遭到污染。

2.實(shí)參傳引用

缺點(diǎn):形參的操作對(duì)實(shí)參會(huì)產(chǎn)生影響,形參的錯(cuò)誤操作會(huì)讓實(shí)參數(shù)據(jù)遭到修改。

優(yōu)點(diǎn):因?yàn)樾螀⑹菍?shí)參的引用,一定程序上,可以提高程序的運(yùn)行速度

引用做函數(shù)返回值

在了解引用做返回值時(shí),我們還是得先了解傳值返回和傳引用返回的區(qū)別。其實(shí)原理和上面大致相同。

1.傳值返回

在返回c的時(shí)候,返回的不是c的本體,而是將c拷貝在一塊臨時(shí)空間里,所以返回的其實(shí)是這塊臨時(shí)空間。然后ret再次拷貝一個(gè)和這塊臨時(shí)空間一樣數(shù)據(jù)的空間。

這塊有點(diǎn)像俄羅斯套娃,需要多畫圖理解。我一開始也有點(diǎn)懵逼。多畫圖就清晰了。

但是問題又來了,這塊臨時(shí)拷貝空間又存儲(chǔ)在哪里呢?

當(dāng)c比較小的時(shí)候(4字節(jié)或者8字節(jié)),一般是存儲(chǔ)在寄存器中。

當(dāng)c比較大的時(shí)候,臨時(shí)變量放在該函數(shù)的棧幀上面。

接下來我們通過觀察代碼的反匯編進(jìn)行證明:

分析這段代碼的匯編,在進(jìn)入add函數(shù)以后,先是將a的值給了eax,然后將b的值加上a,接著將eax里的值給了c。最后對(duì)c進(jìn)行返回,在返回c的時(shí)候生成一個(gè)臨時(shí)拷貝,c將自己的值又給到了寄存器eax中。

最后回到主函數(shù),eax將值給了ret。

傳引用返回

這里進(jìn)行的是傳引用返回,也就是說ret其實(shí)就是c的別名。傳引用返回,返回的就是本體,而不是拷貝。因?yàn)檫@里c是一個(gè)局部變量,在函數(shù)結(jié)束以后,棧幀被銷毀,局部變量的空間被系統(tǒng)回收了。這時(shí)ret再去訪問c的內(nèi)容就可能造成非法訪問,并且c的值可能已經(jīng)被修改了。

形象的來說:就是你原先買了一個(gè)房子,后面你又將其賣給了別人,后面你想再次進(jìn)入這個(gè)房子,但是這間房子已經(jīng)不屬于你了,你進(jìn)房子的操作就屬于非法訪問了。

所以,傳引用返回時(shí),返回的對(duì)象不能是出函數(shù)就被系統(tǒng)回收的。也就是說返回的變量不能是一個(gè)局部變量。

引用的權(quán)限

1.引用的權(quán)限可以縮小

int main() {
int a = 10;
const int &b = a;//權(quán)限的縮小
}

這里變量a是可讀可寫的,而b是a的引用,b只能對(duì)a這塊內(nèi)存空間進(jìn)行讀取,不能進(jìn)行修改,這就是權(quán)限的縮小,這在C++中是可以的。

2.引用的權(quán)限不能放大

int main() {
const int a = 10;
int &b = a;//權(quán)限的縮小
}

這里變量a指向的空間是只能讀取的,不能進(jìn)行修改,而a的引用b,是可以對(duì)a指向的這塊空間進(jìn)行修改的,使得權(quán)限得到了放大,這種語法在C++中是錯(cuò)誤的。

總結(jié):引用可以進(jìn)行權(quán)限的縮小,但是不能進(jìn)行權(quán)限的放大

引用經(jīng)典筆試題

下圖中的代碼(1)和(2)是否能夠正常運(yùn)行?

double d=11.1;
int a=d;(1)
int &ret=d;(2)

答案:(1)可以運(yùn)行通過,(2)不行。

代碼(1)是普通的隱式類型轉(zhuǎn)換。

而在了解代碼(2)的錯(cuò)誤原因之前,我們需要回顧一些知識(shí):

產(chǎn)生臨時(shí)變量的情況

1.類型轉(zhuǎn)換

double d=11.1;

int a=d;

d的類型是double,a的類型是int,類型不同,正如下圖所示,在發(fā)生隱式類型轉(zhuǎn)換的時(shí)候,需要將d的值存到一個(gè)int類型的臨時(shí)變量里,然后將這個(gè)臨時(shí)變量的值賦予給a。

2.整形提升

int a=10

char c=‘b’;

if(a>c){

}

這里并不是拿c直接和a進(jìn)行比較,而是將c賦值到一個(gè)int的臨時(shí)變量里,通過這個(gè)臨時(shí)變量去和a進(jìn)行比較。

關(guān)于右值

結(jié)論:右值是具有常性的,是不可修改的。

這里的右值不能通過字面意思(處于式子右邊的值)進(jìn)行理解,以下的幾種情況一般都是屬于右值。

1.表達(dá)式的計(jì)算結(jié)果: 如:5+3=8,這里的8就是右值。

2.常量:如a=5,這里的5就是右值。

3.一些隱式類型轉(zhuǎn)換產(chǎn)生的臨時(shí)變量。如

int a;

double d;

d=a;

這里隱式類型轉(zhuǎn)換產(chǎn)生的臨時(shí)變量也是一種右值。

在明白了這些基礎(chǔ)原理以后,我們開始學(xué)習(xí)為什么代碼int &ret=d;(2)是錯(cuò)誤的。

這里引用的變量其實(shí)是一塊臨時(shí)空間,而臨時(shí)空間是右值是不能修改的,這種引用的方式本質(zhì)上其實(shí)就是權(quán)限的放大,因此編譯不能通過。

引用的底層原理

int main() {
int a;
int &b = a;
int *p = &a;
}

這里通過調(diào)試模式觀看這段代碼的反匯編。

這里的lea是取地址的意思。 從匯編代碼可以看出,在底成實(shí)現(xiàn)的時(shí)候,引用和指針的實(shí)現(xiàn)方式是一樣的,所以說: 引用的底層是通過指針實(shí)現(xiàn)的

到此這篇關(guān)于C++詳細(xì)分析引用的使用及其底層原理的文章就介紹到這了,更多相關(guān)C++引用的使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++ LeetCode1775通過最少操作次數(shù)使數(shù)組和相等

    C++ LeetCode1775通過最少操作次數(shù)使數(shù)組和相等

    這篇文章主要為大家介紹了C++ LeetCode1775通過最少操作次數(shù)使數(shù)組和相等,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 聊一聊OpenCV相機(jī)標(biāo)定

    聊一聊OpenCV相機(jī)標(biāo)定

    這篇文章主要為大家詳細(xì)介紹了OpenCV相機(jī)標(biāo)定的相關(guān)資料,即獲得相機(jī)參數(shù)的過程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • C語言float內(nèi)存布局示例詳解

    C語言float內(nèi)存布局示例詳解

    這篇文章主要為大家介紹了C語言float內(nèi)存布局示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Matlab實(shí)現(xiàn)好看的配對(duì)箱線圖的繪制

    Matlab實(shí)現(xiàn)好看的配對(duì)箱線圖的繪制

    配對(duì)箱線圖,常見于配對(duì)樣本的數(shù)據(jù)分析中,它除了能夠表現(xiàn)兩組的整體差異,還能夠清晰地呈現(xiàn)單個(gè)樣本的前后改變。本文將用Matlab實(shí)現(xiàn)配對(duì)箱線圖的繪制,需要的可以參考一下
    2022-08-08
  • c++中map容器的使用詳解

    c++中map容器的使用詳解

    這篇文章主要介紹了c++中map容器的使用詳解,C++中map容器提供一個(gè)鍵值對(duì)容器,map與multimap差別僅僅在于multiple允許一個(gè)鍵對(duì)應(yīng)多個(gè)值,需要的朋友可以參考下
    2023-08-08
  • 詳解C語言中strcpy函數(shù)與memcpy函數(shù)的區(qū)別與實(shí)現(xiàn)

    詳解C語言中strcpy函數(shù)與memcpy函數(shù)的區(qū)別與實(shí)現(xiàn)

    這篇文章主要介紹了C語言中字符串拷貝函數(shù)(strcpy)與內(nèi)存拷貝函數(shù)(memcpy)的不同及內(nèi)存拷貝函數(shù)的模擬實(shí)現(xiàn),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-12-12
  • c++驗(yàn)證哥德巴赫猜想

    c++驗(yàn)證哥德巴赫猜想

    這篇文章主要介紹了c++驗(yàn)證哥德巴赫猜想,哥德巴赫猜想就是任一大于2的偶數(shù),都可表示成兩個(gè)素?cái)?shù)之和,需要的朋友可以參考下
    2014-04-04
  • Java C++題解leetcode判定是否為字符重排

    Java C++題解leetcode判定是否為字符重排

    這篇文章主要為大家介紹了Java C++題解leetcode判定是否為字符重排,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 二叉樹遍歷 非遞歸 C++實(shí)現(xiàn)代碼

    二叉樹遍歷 非遞歸 C++實(shí)現(xiàn)代碼

    對(duì)于二叉樹,有前序、中序以及后序三種遍歷方法。因?yàn)闃涞亩x本身就是遞歸定義,因此采用遞歸的方法去實(shí)現(xiàn)樹的三種遍歷不僅容易理解而且代碼很簡(jiǎn)潔。而對(duì)于樹的遍歷若采用非遞歸的方法,就要采用棧去模擬實(shí)現(xiàn)
    2013-09-09
  • 詳解C++中的ANSI與Unicode和UTF8三種字符編碼基本原理與相互轉(zhuǎn)換

    詳解C++中的ANSI與Unicode和UTF8三種字符編碼基本原理與相互轉(zhuǎn)換

    在C++編程中,我們有時(shí)需要去處理字符串編碼的相關(guān)問題,常見的字符編碼有ANSI窄字節(jié)編碼、Unicode寬字節(jié)編碼及UTF8可變長(zhǎng)編碼。很多人在處理字符串編碼問題時(shí)都會(huì)有疑惑,即便是有多年工作經(jīng)驗(yàn)的朋友也可能搞不清楚。所以有必要講一下這三種字符編碼以及如何去使用它們
    2021-11-11

最新評(píng)論