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

C++引用概念及用法全解

 更新時(shí)間:2026年04月06日 08:08:18   投稿:mrr  
本文詳細(xì)介紹了C++中的引用概念,總結(jié)了引用和指針的關(guān)鍵差異,并強(qiáng)調(diào)引用更安全但靈活性較低,指針則更靈活但需注意空指針等問(wèn)題,感興趣的朋友跟隨小編一起看看吧

一、什么是引用?

引用是C++中的一種語(yǔ)法特性,可以理解為變量的別名。引用本身不占用獨(dú)立的內(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)鍵點(diǎn):對(duì)引用的操作就是對(duì)原變量的操作,兩者完全等價(jià)。

二、引用的三大特點(diǎn)

1. 定義引用時(shí)必須初始化

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

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

2. 不存在空引用

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

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

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

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

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

對(duì)比指針

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

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

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

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

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

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

// C語(yǔ)言:傳值,交換失敗
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,沒(méi)變
}

想要修改實(shí)參,必須傳指針

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

C++的引用可以做到同樣的事,語(yǔ)法更簡(jiǎn)潔:

// 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)用時(shí)和傳值一樣,但實(shí)參被改了
    cout << x << " " << y << endl;  // 輸出20 10
}

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

2. 避免拷貝,提高效率

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

// 傳值:拷貝整個(gè)Student對(duì)象(幾十字節(jié))
void PrintStudent(Student s) { ... }

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

注意:對(duì)于 intchar 這類(lèi)小型數(shù)據(jù),傳值反而更快,因?yàn)橹苯訌?fù)制到寄存器,不需要間接訪問(wèn)。所以小型數(shù)據(jù)用傳值,大型對(duì)象用const引用。

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

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

四、普通引用 vs const引用

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

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

2. const引用(只讀)

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

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

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

  • 原變量是普通變量(可讀可寫(xiě))→ 引用可以是普通引用,也可以是常引用
  • 原變量是常量(只讀)→ 引用只能是常引用
int a = 10;        // 普通變量:可讀可寫(xiě)
const int b = 20;  // 常量:只讀

int& ra = a;        // ? 普通引用引用普通變量
const int& cra = a; // ? 常引用引用普通變量

int& rb = b;        // ? 錯(cuò)誤:普通引用不能引用常量(權(quán)限超了)
const int& crb = b; // ? 常引用引用常量

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

五、const引用的萬(wàn)能特性

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

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 引用綁定到字面常量時(shí),編譯器會(huì)生成一個(gè)臨時(shí)變量來(lái)保存這個(gè)常量,然后讓引用指向這個(gè)臨時(shí)變量。

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

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

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

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

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

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

int a = 10, b = 20;
int& ra = a;   // ra是a的別名

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

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

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

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

原因sizeof 作用于引用時(shí),返回的是被引用對(duì)象的大小。

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

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

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

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

先看一個(gè)錯(cuò)誤示例

Student& func() {
    Student sa{ "S001", "Alice", "F", 20  };
    return sa;   // 返回局部變量的引用
}

int main() {
    Student& p = func();
    printf("%s", p.s_name);  // 可能崩潰,可能亂碼,可能碰巧正確
}

為什么錯(cuò)了?

困惑1:返回地址本身有什么錯(cuò)?

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

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

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

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

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

// 返回引用:返回地址,危險(xiǎn)
Student& func1() {
    Student sa{ ... };
    return sa;   // 返回地址,sa銷(xiāo)毀后地址失效 ?
}

// 返回值:返回副本,安全
Student func2() {
    Student sa{ ... };
    return sa;   // 返回副本,sa銷(xiāo)毀不影響副本 ?
}

區(qū)別

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

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

看返回類(lèi)型:

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

類(lèi)比理解

你在酒店開(kāi)房:

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

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

正確的做法

1. 返回值(拷貝)

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

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

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

3. 在堆上分配

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

一句話(huà)總結(jié)

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

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

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

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

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

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

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

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

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

3. 對(duì)比

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

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

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

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

數(shù)組名在三種情況下不會(huì)退化,保持為整個(gè)數(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ù):退化問(wèn)題

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

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

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

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

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

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

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

對(duì)比項(xiàng)引用指針
本質(zhì)變量的別名存儲(chǔ)變量的地址
內(nèi)存分配不分配獨(dú)立內(nèi)存分配4/8字節(jié)內(nèi)存
使用方式直接使用需要解引用(*)
能否改變指向不能
必須初始化
是否可為空不能可以(NULL/nullptr)
sizeof結(jié)果原變量的大小指針本身的大?。?/8)
多級(jí)無(wú)(無(wú)引用的引用)有(二級(jí)、n級(jí)指針)
++操作改變?cè)兞康闹?/td>改變指向的地址
// 演示++操作的區(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ì)

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

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

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

3. 一句話(huà)總結(jié)

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

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

總結(jié)

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

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

相關(guān)文章

最新評(píng)論

昌乐县| 新宁县| 湘潭县| 浦东新区| 定远县| 威海市| 安福县| 中山市| 孝昌县| 两当县| 宜兴市| 陆川县| 芜湖市| 封丘县| 天台县| 星座| 德令哈市| 通道| 宜昌市| 山阴县| 那坡县| 堆龙德庆县| 建始县| 鹿邑县| 百色市| 安福县| 霞浦县| 五寨县| 崇文区| 葵青区| 公主岭市| 邵东县| 定南县| 新田县| 怀远县| 常德市| 霍城县| 高青县| 安阳市| 枣阳市| 木兰县|