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

C++深入探究引用的本質與意義

 更新時間:2022年04月24日 11:29:19   作者:清風自在?流水潺潺  
引用是C++一個很重要的特性,顧名思義是某一個變量或對象的別名,對引用的操作與對其所綁定的變量或對象的操作完全等價,這篇文章主要給大家總結介紹了C++中引用的相關知識點,需要的朋友可以參考下

一、引用的意義

  • 引用作為變量別名而存在,因此在一些場合可以代替指針
  • 引用相對于指針來說具有更好的可讀性和實用性

下面通過代碼來進行說明,在C語言中,可以這么寫:

#include <stdio.h>
void swap(int* a, int* b)
{
	int t = *a;
	*a = *b;
	*b = t;
}
int main()
{
	int a = 1;
	int b = 2;
	swap(&a, &b);
	printf("a = %d, b = %d\n", a, b);
	return 0;
}

下面為輸出結果,可以看到a,b被交換。

若采用C++用的引用,則采用下面的代碼:

#include <stdio.h>
void swap(int& a, int& b)
{
	int t = a;
	a = b;
	b = t;
}
int main()
{
	int a = 1;
	int b = 2;
	swap(a, b);
	printf("a = %d, b = %d\n", a, b);
	return 0;
}

下面為輸出結果,需要注意的是,引用作為函數(shù)的形參時,不需要進行初始化,初始化發(fā)生在函數(shù)調用的時候(形參一旦被初始化后,就代表兩個具體的外部變量)。

二、特殊的引用

const 引用

  • 在C++中可以聲明const 引用
  • const Type& name = var ;
  • const 引用讓變量擁有只讀屬性
  • 當使用常量對const引用進行初始化時,C++編譯器會為常量值分配空間,并將引用名作為這段空間的別名

所以上面那段代碼,b = 5 是不正確的,因為 b 已經是只讀變量了,但是依舊可以通過指針改變這個只讀變量的值。

結論:使用常量對const 引用初始化后將生成一個只讀變量

下面看一段代碼,加深理解:

#include <stdio.h>
void Example()
{
    printf("Example:\n");
    int a = 4;
    const int& b = a;
    int* p = (int*)&b;
    //b = 5;
    *p = 5;
    printf("a = %d\n", a);
    printf("b = %d\n", b);
}
void Demo()
{
    printf("Demo:\n");
    const int& c = 1;
    int* p = (int*)&c;
    //c = 5;
    *p = 5;
    printf("c = %d\n", c);
}
int main(int argc, char *argv[])
{
    Example();
    printf("\n");
    Demo();
    return 0;
}

下面為輸出結果:

如果把那兩行(b = 5,c = 5)取消注釋,則就會輸出下面結果,編譯器會報 b 和 c 都是只讀變量的錯誤。

三、引用是否占用存儲空間

下面看一段代碼:

#include <stdio.h>
struct TRef
{
    char& r;
};
int main(int argc, char *argv[])
{ 
    char c = 'c';
    char& rc = c;
    TRef ref = { c };
    printf("sizeof(char&) = %d\n", sizeof(char&));	//char類型占用一個字節(jié) 1
    printf("sizeof(rc) = %d\n", sizeof(rc));	//sizeof(c) => 1
    printf("sizeof(TRef) = %d\n", sizeof(TRef));	//?
    printf("sizeof(ref.r) = %d\n", sizeof(ref.r));	//sizeof(c) => 1
    return 0;
}

下面為輸出結果,可以看到sizeof(TRef)占用的內存空間為4,我們知道指針占用的內存空間為4,那么指針和引用到底有什么關系呢?第4節(jié)來分析。

四、引用的本質

引用在C++中的內部實現(xiàn)是一個指針常量

注意:

  • C++編譯器在編譯過程中用指針常量作為引用的內部實現(xiàn),因此引用所占用的空間大小與指針相同。
  • 從使用的角度,引用只是一個別名,C++為了實用性而隱藏了引用的存儲空間這一細節(jié)。

通過下面的代碼,也可以很好的理解引用所占的字節(jié)數(shù):

#include <stdio.h>
struct TRef
{
    char* before;
    char& ref;
    char* after;
};
int main(int argc, char* argv[])
{
    char a = 'a';
    char& b = a;
    char c = 'c';
    TRef r = {&a, b, &c};
    printf("sizeof(r) = %d\n", sizeof(r));
    printf("sizeof(r.before) = %d\n", sizeof(r.before));
    printf("sizeof(r.after) = %d\n", sizeof(r.after));
    printf("&r.before = %p\n", &r.before);
    printf("&r.after = %p\n", &r.after);
    return 0;
}

下面為輸出結果,可以看到結構體占用12個字節(jié),before 和 after 指針各占用4個字節(jié),所以 ref 引用當然也占用4個字節(jié),通過 after 的起始內存地址減上 before 的起始內存地址得8,而 before 指針占用4個字節(jié),從這個層面也能知道 ref 引用占用4個字節(jié)。

為了深入理解引用的本質,可以在 Visual Studio 2012 中進行反匯編,如下圖,現(xiàn)在return 0那里打個斷點,然后點擊本地 Windows 調試器,開始執(zhí)行代碼。

執(zhí)行完代碼后,鼠標右擊空白區(qū)域,選擇轉到反匯編。

下面看一下反匯編的部分代碼,主要看引用那部分的匯編代碼,lea eax,[a] 表示取a的地址,存到 eax 寄存器中,mov dword ptr [b],eax表示把a 的地址保存到 b 所對應的4個內存空間里面去??梢赃@么說,引用的內部實現(xiàn)就是指針,所以引用占用內存空間,且占用內存空間大小和指針一樣。

五、引用的注意事項

C++中的引用旨在大多數(shù)的情況下代替指針

  • 功能性:可以滿足多數(shù)需要使用指針的場合
  • 安全性∶可以避開由于指針操作不當而帶來的內存錯誤
  • 操作性∶簡單易用,又不失功能強大

下面通過一個函數(shù)返回引用,介紹一下引用的注意事項。

#include <stdio.h>
int& demo()    //從內部實現(xiàn)來看,想返回一個指針 int* const
{
    int d = 0;
    printf("demo: d = %d\n", d);
    return d; //本質上,相當于 return &d
}
int& func()
{
    static int s = 0;
    printf("func: s = %d\n", s);
    return s;    //本質上,相當于 return &s
}
int main(int argc, char* argv[])
{
    int& rd = demo();
    int& rs = func();
    printf("\n");
    printf("main: rd = %d\n", rd);
    printf("main: rs = %d\n", rs);
    printf("\n");
    rd = 10;
    rs = 11;
    demo();
    func();
    printf("\n");
    printf("main: rd = %d\n", rd);
    printf("main: rs = %d\n", rs);
    printf("\n");
    return 0;
}

下面為輸出結果,可以看到編譯的時候開始發(fā)出警告說不能返回局部變量,如果繼續(xù)運行,可以看到 rd = 9658356,rd 為 d 的別名,按理說應該輸出 0 的,為什么輸出9658356 呢?這個因為 rd 所代表的的變量在 demo 函數(shù)調用返回的時候被摧毀了,其所代表的是一個不存在的變量,所以 rd 沒有意義了。

引用中必須遵守的規(guī)則:不要返回局部變量的引用。 如果局部變量是靜態(tài)的,則可以。因為靜態(tài)局部變量的存儲區(qū)是全局的存儲區(qū),所以它的空間不會因為函數(shù)的返回而被摧毀。

六、小結

  • 引用作為變量別名而存在旨在代替指針
  • const 引用可以使得變量具有只讀屬性
  • 引用在編譯器內部使用指針常量實現(xiàn)
  • 引用的最終本質為指針
  • 引用可以盡可能的避開內存錯誤

到此這篇關于C++深入探究引用的本質與意義的文章就介紹到這了,更多相關C++引用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • VS及Unity安裝和使用Nuget包

    VS及Unity安裝和使用Nuget包

    本文主要介紹了VS及Unity安裝和使用Nuget包,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • C/C++通過HTTP實現(xiàn)文件上傳與下載的示例詳解

    C/C++通過HTTP實現(xiàn)文件上傳與下載的示例詳解

    WinInet是 Microsoft Windows 操作系統(tǒng)中的一個 API 集,用于提供對 Internet 相關功能的支持,它包括了一系列的函數(shù),使得 Windows 應用程序能夠進行網絡通信、處理 HTTP 請求、FTP 操作等,本文給大家介紹了C/C++通過HTTP實現(xiàn)文件上傳與下載,需要的朋友可以參考下
    2023-12-12
  • C++ 計數(shù)排序實例詳解

    C++ 計數(shù)排序實例詳解

    這篇文章主要介紹了C++ 計數(shù)排序實例詳解的相關資料,需要的朋友可以參考下
    2017-07-07
  • C++事件驅動型銀行排隊模擬

    C++事件驅動型銀行排隊模擬

    這篇文章主要為大家詳細介紹了C++事件驅動型銀行排隊模擬,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • C++的數(shù)據類型你真的了解嗎

    C++的數(shù)據類型你真的了解嗎

    這篇文章主要為大家詳細介紹了C++的數(shù)據類型,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • 詳解C++ 重載運算符和重載函數(shù)

    詳解C++ 重載運算符和重載函數(shù)

    這篇文章主要介紹了C++ 重載運算符和重載函數(shù)的的相關資料,文中示例代碼非常詳細,幫助大家更好的理解和學習,感興趣的朋友可以了解下
    2020-07-07
  • C++字符串輸入緩沖區(qū)機制詳解

    C++字符串輸入緩沖區(qū)機制詳解

    緩沖區(qū)是用來存放流中的數(shù)據,本文詳細的介紹了C++字符串輸入緩沖區(qū)機制,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-10-10
  • C語言之預處理命令的深入講解

    C語言之預處理命令的深入講解

    這篇文章主要給大家介紹了關于C語言之預處理命令的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • C++中單鏈表操作的示例代碼

    C++中單鏈表操作的示例代碼

    這篇文章主要為大家詳細介紹了C++中單鏈表操作的示例代碼,主要包括單鏈表的創(chuàng)建、元素的插入和刪除等。文中的代碼簡潔易懂,需要的可以參考一下
    2022-10-10
  • c語言中實現(xiàn)數(shù)組幾個數(shù)求次大值

    c語言中實現(xiàn)數(shù)組幾個數(shù)求次大值

    這篇文章主要介紹了c語言中實現(xiàn)數(shù)組幾個數(shù)求次大值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12

最新評論