最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++引用及基本用法全解

 更新時間:2026年04月13日 10:27:17   作者:CoderMeijun  
本文解釋了C++中的引用概念,包括引用的三大特點(必須初始化、不能為空、不能改指向)、引用作為函數(shù)參數(shù)的三種方式、const引用的萬能特性、引用與指針的區(qū)別等,感興趣的朋友跟隨小編一起看看吧

一、什么是引用?

引用是C++中的一種語法特性,可以理解為變量的別名。引用本身不占用獨立的內(nèi)存空間,它和被引用的變量共享同一塊內(nèi)存。

引用的基本用法

int main() {
    int a = 10;
    int& ra = a;  // ra是a的別名
    a += 10;
    cout << ra << endl;  // 輸出20
    ra += 10;
    cout << a << endl;   // 輸出30
    return 0;
}

關(guān)鍵點:對引用的操作就是對原變量的操作,兩者完全等價。

二、引用的三大特點

1. 定義引用時必須初始化

int& ra;      // ? 錯誤:引用必須初始化
int& ra = a;  // ? 正確

原因:引用是變量的別名,別名必須依附于某個已存在的變量,不能獨立存在。

2. 不存在空引用

int& ra = NULL;  // ? 錯誤:不能給引用賦空值
int* p = NULL;   // ? 指針可以為空

原因:引用必須綁定到一個有效的變量,不能指向空地址。指針是獨立的變量,可以存儲空地址,但引用不是變量,它只是別名。

3. 引用一旦綁定,不能改變指向

int a = 10, b = 20;
int& ra = a;
ra = b;  // 這不是讓ra指向b,而是把b的值賦給a(即a = 20)

原因:引用在初始化時綁定了目標(biāo)變量,之后所有對引用的操作都直接作用于該變量,無法重新綁定到其他變量。

對比指針

int a = 10, b = 20;
int* p = &a;   // 指針可以改變指向
p = &b;        // 現(xiàn)在p指向b
*p = 100;      // 修改b的值為100

三、引用作為函數(shù)參數(shù)

引用的本質(zhì):引用是變量的別名,不是副本。對引用的操作就是對原變量的操作。

基于這個特性,引用最常用的場景是作為函數(shù)參數(shù),主要解決兩個問題:

1. 在函數(shù)內(nèi)部修改外部變量

C語言中,函數(shù)參數(shù)默認(rèn)是傳值:形參是實參的副本,函數(shù)內(nèi)部修改形參,外面的實參不受影響。

// C語言:傳值,交換失敗
void Swap(int a, int b) {
    int tmp = a;
    a = b;
    b = tmp;
}
int main() {
    int x = 10, y = 20;
    Swap(x, y);
    // x和y還是10和20,沒變
}

想要修改實參,必須傳指針

// C語言:傳指針,交換成功
void Swap(int* a, int* b) {
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

C++的引用可以做到同樣的事,語法更簡潔:

// C++:傳引用,交換成功
void Swap(int& a, int& b) {
    int tmp = a;
    a = b;
    b = tmp;
}
int main() {
    int x = 10, y = 20;
    Swap(x, y);     // 調(diào)用時和傳值一樣,但實參被改了
    cout << x << " " << y << endl;  // 輸出20 10
}

優(yōu)點:調(diào)用時不用取地址,函數(shù)內(nèi)部不用解引用,代碼更清晰。

2. 避免拷貝,提高效率

當(dāng)參數(shù)是大型對象(如結(jié)構(gòu)體、類)時,傳值會拷貝整個對象,開銷很大。傳引用只傳遞地址(4/8字節(jié)),效率更高。

// 傳值:拷貝整個Student對象(幾十字節(jié))
void PrintStudent(Student s) { ... }
// 傳引用:只傳遞地址(4/8字節(jié)),不拷貝
void PrintStudent(const Student& s) { ... }

注意:對于 intchar 這類小型數(shù)據(jù),傳值反而更快,因為直接復(fù)制到寄存器,不需要間接訪問。所以小型數(shù)據(jù)用傳值,大型對象用const引用

3. 三種參數(shù)傳遞方式對比

方式本質(zhì)能否修改實參效率(小型數(shù)據(jù))效率(大型對象)
傳值副本? 不能
傳指針地址? 能
傳引用別名? 能

四、普通引用 vs const引用

1. 普通引用(可讀可寫)

int a = 10;
int& ra = a;   // 普通引用
ra = 100;      // ? 可以修改
cout << ra;    // ? 可以讀取

2. const引用(只讀)

int a = 10;
const int& cra = a;  // 常引用,只讀
cout << cra;         // ? 可以讀取
cra = 100;           // ? 錯誤:不能通過常引用修改

3. 權(quán)限規(guī)則:看原變量的權(quán)限

引用的權(quán)限不能超過原變量。

  • 原變量是普通變量(可讀可寫)→ 引用可以是普通引用,也可以是常引用
  • 原變量是常量(只讀)→ 引用只能是常引用
int a = 10;        // 普通變量:可讀可寫
const int b = 20;  // 常量:只讀
int& ra = a;        // ? 普通引用引用普通變量
const int& cra = a; // ? 常引用引用普通變量
int& rb = b;        // ? 錯誤:普通引用不能引用常量(權(quán)限超了)
const int& crb = b; // ? 常引用引用常量

一句話:變量是什么權(quán)限,引用就不能超過這個權(quán)限。

五、const引用的萬能特性

const引用可以引用任何東西:普通變量、常變量、字面常量,甚至臨時對象。

1. 引用普通變量

int a = 10;
const int& cra = a;  // ?

2. 引用常變量

const int b = 20;
const int& crb = b;  // ?

3. 引用字面常量

const int& crx = 30;  // ? 可以!

背后原理

當(dāng) const 引用綁定到字面常量時,編譯器會生成一個臨時變量來保存這個常量,然后讓引用指向這個臨時變量。

// 編譯器實際做的事:
int tmp = 30;
const int& crx = tmp;

注意:引用本身不占內(nèi)存,但被引用的對象(臨時變量)需要占內(nèi)存。這個臨時變量由編譯器自動創(chuàng)建和管理,它的生命周期和引用一致。

4. 引用表達(dá)式結(jié)果

int a = 10, b = 20;
const int& cr = a + b;  // ? 表達(dá)式結(jié)果是臨時變量,const引用可以綁定

六、引用的常見誤區(qū)

誤區(qū)1:引用可以重新綁定

int a = 10, b = 20;
int& ra = a;   // ra是a的別名
ra = b;        // ? 不是讓ra指向b,而是把b的值賦給a(a變成20)

誤區(qū)2:引用占用空間

引用本身不占用獨立內(nèi)存,它只是原變量的別名。sizeof 引用的結(jié)果是原變量的大小。

int a = 10;
int& ra = a;
cout << sizeof(ra);  // 輸出4(int的大小),不是指針的大小

原因sizeof 作用于引用時,返回的是被引用對象的大小。

誤區(qū)3:引用可以指向引用

int a = 10;
int& ra = a;
int&& rra = ra;  // ? 錯誤:不存在"引用的引用"

原因:引用是別名,不是對象。不能給別名再起別名嗎?語法上不允許。

七、不能返回局部變量的引用或地址

先看一個錯誤示例

Student& func() {
    Student sa{ "S001", "Alice", "F", 20  };
    return sa;   // 返回局部變量的引用
}
int main() {
    Student& p = func();
    printf("%s", p.s_name);  // 可能崩潰,可能亂碼,可能碰巧正確
}

為什么錯了?

困惑1:返回地址本身有什么錯?

返回地址本身沒錯。return &sa 返回的是一個數(shù)字(內(nèi)存地址),這個操作是合法的。錯的是函數(shù)結(jié)束后你還去用這個地址訪問內(nèi)存

困惑2:為什么函數(shù)結(jié)束后就不能用了?

函數(shù)調(diào)用時,系統(tǒng)會在棧上給局部變量分配空間。函數(shù)結(jié)束后,這塊空間被系統(tǒng)回收,標(biāo)記為“可重用”。但回收不是清零,這塊內(nèi)存還在,只是不再屬于你了。

下次調(diào)用其他函數(shù)時,系統(tǒng)可能會把這塊空間分配給別的變量,里面的內(nèi)容隨時可能被覆蓋。所以你去訪問它,結(jié)果是不可預(yù)測的。

困惑3:返回值和返回引用有什么區(qū)別?

// 返回引用:返回地址,危險
Student& func1() {
    Student sa{ ... };
    return sa;   // 返回地址,sa銷毀后地址失效 ?
}
// 返回值:返回副本,安全
Student func2() {
    Student sa{ ... };
    return sa;   // 返回副本,sa銷毀不影響副本 ?
}

區(qū)別

  • 返回引用:把原件的地址告訴別人,原件沒了,地址就成了空地址
  • 返回值:復(fù)印一份交給別人,原件沒了,復(fù)印件還在

困惑4:返回局部變量的地址,和返回局部變量本身,有什么區(qū)別?

看返回類型:

  • 返回類型是 Student& 或 Student*:返回的是地址(危險)
  • 返回類型是 Student:返回的是副本(安全)
Student& func1() { return sa; }  // 返回類型是引用 → 地址
Student* func2() { return &sa; } // 返回類型是指針 → 地址
Student func3() { return sa; }   // 返回類型是對象 → 副本

類比理解

你在酒店開房:

  • sa 就是你住的房間
  • 返回引用或地址:你把房間號告訴別人
  • 退房(函數(shù)結(jié)束):房間被回收,不再屬于你
  • 別人拿著房間號回去找:房間可能住了別人,可能在打掃,可能已經(jīng)被改成倉庫
  • 去用這個房間號 → 結(jié)果不可預(yù)測

返回值:你退房時把房間里的東西復(fù)印一份帶走,原來的房間怎么變都跟你無關(guān)。

正確的做法

1. 返回值(拷貝)

Student func() {
    Student sa{ ... };
    return sa;  // 返回副本
}

2. 返回靜態(tài)局部變量

Student& func() {
    static Student sa{ ... };  // 靜態(tài)變量,生命周期貫穿整個程序
    return sa;
}Student& func() {
    static Student sa{ ... };  // 靜態(tài)變量,生命周期貫穿整個程序
    return sa;
}

3. 在堆上分配

Student* func() {
    Student* p = new Student{ ... };  // 堆上分配,手動管理
    return p;
}

一句話總結(jié)

返回局部變量的地址本身沒錯,錯的是函數(shù)結(jié)束后你還去用這個地址。因為這塊內(nèi)存已經(jīng)被系統(tǒng)回收,不再屬于你了。

八、能不能定義引用數(shù)組?

結(jié)論:不能定義“元素為引用的數(shù)組”,但可以定義“數(shù)組的引用”。

1. 不能定義元素為引用的數(shù)組

int& rbr[5];  // ? 錯誤:不能定義引用數(shù)組

原因:數(shù)組是一段連續(xù)的內(nèi)存空間,每個元素都需要占用內(nèi)存。引用本身不占內(nèi)存,它只是別名,無法作為數(shù)組元素存在。

2. 可以定義數(shù)組的引用

int ar[5] = {1,2,3,4,5};
int(&rar)[5] = ar;  // ? 正確:rar是數(shù)組ar的引用

含義rar 是整個數(shù)組 ar 的別名,不是元素為引用的數(shù)組。

3. 對比

寫法含義是否正確
int& rbr[5]元素為引用的數(shù)組? 錯誤
int(&rar)[5]數(shù)組的引用? 正確

記憶技巧:括號位置決定一切。& 靠近數(shù)組名,表示引用整個數(shù)組;& 靠近類型,表示元素是引用。

九、數(shù)組名退化問題

1. 數(shù)組名退化的規(guī)則

數(shù)組名在三種情況下不會退化,保持為整個數(shù)組:

  • sizeof(ar)
  • &ar(取數(shù)組地址)
  • 引用數(shù)組 int(&rar)[n] = ar

其他情況數(shù)組名退化為數(shù)組首元素的地址。

int ar[5] = {1,2,3,4,5};
cout << sizeof(ar);      // 20(5*4,未退化)
int(*p)[5] = &ar;        // 取數(shù)組地址,未退化
int(&rar)[5] = ar;       // 引用數(shù)組,未退化
int* q = ar;             // 退化:ar變成int*

2. 數(shù)組名作為函數(shù)參數(shù):退化問題

C++中,數(shù)組名作為參數(shù)傳遞給函數(shù)時,會退化為指針,丟失數(shù)組大小信息。

void funa(int br[5]) {
    cout << sizeof(br);   // 輸出8(指針大?。?,不是20
    // 函數(shù)內(nèi)部不知道數(shù)組有多大,只能通過額外參數(shù)傳入長度
}

如果希望函數(shù)內(nèi)部能知道數(shù)組的大小,可以用數(shù)組的引用作為參數(shù):

void funb(int (&rar)[5]) {
    cout << sizeof(rar);  // 輸出20,保留了數(shù)組大小
    // 函數(shù)內(nèi)部可以直接用sizeof獲取數(shù)組長度
}

關(guān)鍵點:用數(shù)組的引用作為參數(shù),可以保留數(shù)組的大小信息,避免退化。

十、引用與指針的區(qū)別

1. 語法規(guī)則上的區(qū)別

對比項引用指針
本質(zhì)變量的別名存儲變量的地址
內(nèi)存分配不分配獨立內(nèi)存分配4/8字節(jié)內(nèi)存
使用方式直接使用需要解引用(*)
能否改變指向不能
必須初始化
是否可為空不能可以(NULL/nullptr)
sizeof結(jié)果原變量的大小指針本身的大小(4/8)
多級無(無引用的引用)有(二級、n級指針)
++操作改變原變量的值改變指向的地址
// 演示++操作的區(qū)別
int ar[5] = {10,20,30,40,50};
int& ra = ar[0];
int* p = &ar[0];
++ra;   // ar[0]變成11
++p;    // p指向ar[1]

2. 匯編層面的本質(zhì)

從匯編角度看,指針和引用沒有區(qū)別,都是地址。

int a = 10;
int& ra = a;
int* p = &a;
// 底層實現(xiàn):ra和p都是存儲a的地址

引用在底層也是用指針實現(xiàn)的,只是編譯器做了語法糖,讓使用更方便、更安全。

3. 一句話總結(jié)

維度引用指針
語法層面別名,更安全地址,更靈活
匯編層面都是地址都是地址

使用建議:能用引用就用引用,需要改變指向或可為空時再用指針。

總結(jié)

知識點核心要點
引用本質(zhì)變量的別名,不占獨立內(nèi)存
三大特點必須初始化、不能為空、不能改指向
const引用只讀,可引用普通變量/常變量/字面常量
權(quán)限規(guī)則引用權(quán)限不能超過原變量
const引用萬能可綁定字面常量和臨時對象,編譯器自動生成臨時變量
引用作為參數(shù)可修改外部變量、避免大對象拷貝
返回局部變量不能返回局部變量的引用或地址,函數(shù)結(jié)束后內(nèi)存被回收
數(shù)組的引用可定義數(shù)組引用 int(&rar)[5],不能定義引用數(shù)組 int& rbr[5]
數(shù)組名退化sizeof/&/數(shù)組引用 三種情況不退化,函數(shù)參數(shù)會退化
引用 vs 指針引用更安全(不能為空、不能改指向),指針更靈活

到此這篇關(guān)于C++引用全解的文章就介紹到這了,更多相關(guān)C++引用全解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言 structural body結(jié)構(gòu)體詳解用法

    C語言 structural body結(jié)構(gòu)體詳解用法

    C 數(shù)組允許定義可存儲相同類型數(shù)據(jù)項的變量,結(jié)構(gòu)是 C 編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許您存儲不同類型的數(shù)據(jù)項,結(jié)構(gòu)用于表示一條記錄,假設(shè)您想要跟蹤圖書館中書本的動態(tài),您可能需要跟蹤每本書的下列屬性
    2021-10-10
  • C語言數(shù)據(jù)結(jié)構(gòu)之鏈隊列的基本操作

    C語言數(shù)據(jù)結(jié)構(gòu)之鏈隊列的基本操作

    這篇文章主要為大家介紹了C語言之鏈隊列的基本操作,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • C++中httplib的使用小結(jié)

    C++中httplib的使用小結(jié)

    本文主要介紹了C++中httplib的使用小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-05-05
  • C語言創(chuàng)建線程thread_create()的方法

    C語言創(chuàng)建線程thread_create()的方法

    這篇文章主要介紹了C語言創(chuàng)建線程thread_create()的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • C++解決合并兩個排序的鏈表問題

    C++解決合并兩個排序的鏈表問題

    本文主要介紹了通過C++解決合并兩個排序的鏈表并使新鏈表中的節(jié)點仍然是遞增排序的。文中代碼講解詳細(xì),有需要的朋友可以參考一下
    2021-12-12
  • 淺談Qt信號槽與事件循環(huán)的關(guān)系

    淺談Qt信號槽與事件循環(huán)的關(guān)系

    本文主要介紹了Qt信號槽與事件循環(huán)的關(guān)系,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • C語言中字符串庫函數(shù)的實現(xiàn)及模擬

    C語言中字符串庫函數(shù)的實現(xiàn)及模擬

    C語言中有很多數(shù)據(jù)類型,比如int(整數(shù)類型)、char(字符類型)、以及浮點型的double(雙精度)等。但是有一點就是我們發(fā)現(xiàn)這里并沒有提到我們常見的有關(guān)字符串的類型。本文為大家介紹了C語言中字符串庫函數(shù)的實現(xiàn)及模擬,需要的可以參考一下
    2022-11-11
  • C語言的隨機數(shù)rand()函數(shù)詳解

    C語言的隨機數(shù)rand()函數(shù)詳解

    這篇文章主要為大家詳細(xì)介紹了C語言的隨機數(shù)rand()函數(shù),使用數(shù)據(jù)庫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • 判斷指定的進(jìn)程或程序是否存在方法小結(jié)(vc等)

    判斷指定的進(jìn)程或程序是否存在方法小結(jié)(vc等)

    VC判斷進(jìn)程是否存在?比如我想知道記事本是否運行,要用到哪些函數(shù)等實例,需要的朋友可以參考下
    2013-01-01
  • Qt中JSON使用的詳細(xì)步驟

    Qt中JSON使用的詳細(xì)步驟

    本文主要介紹了Qt中JSON使用的詳細(xì)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08

最新評論

嵊泗县| 丹东市| 焦作市| 东乡族自治县| 正镶白旗| 庄河市| 昌吉市| 兴仁县| 兰西县| 白玉县| 江山市| 清丰县| 巴里| 恭城| 大渡口区| 济宁市| 定结县| 施甸县| 上饶县| 吕梁市| 古蔺县| 肇州县| 漳浦县| 呈贡县| 平武县| 耒阳市| 蒙阴县| 泾川县| 永年县| 九江市| 大邑县| 武汉市| 洱源县| 阿图什市| 星子县| 陈巴尔虎旗| 仙居县| 武乡县| 兴仁县| 临清市| 莱芜市|