目錄
1.什么是引用
2.引用的定義
?3.引用的特性
4.引用的使用
4.1引用傳參
4.2傳引用返回
5.const引用(在引用的定義前用const修飾)
5.1對于引用
5.2對于指針
6.引用&指針
總結
1.什么是引用
引用就是給變量起別名,一個變量可以有多個別名,引用變量不會另辟空間,語法上和被引用的變量公用同一塊空間,就像一個人可以有多個稱號,所有稱號都是再說一個人。
2.引用的定義
類型& 引用別名 =被引用對象;
?3.引用的特性
- 引用在定義時必須初始化
- 一個變量可以有多個引用
- 引用一旦引用一個實體就不能再引用其他實體
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
int main()
{const char* jjxt= "帥哥";const char*& x = jjxt;const char*& bozhu = jjxt;int a = 1;int& b = a;int& c = b;cout << jjxt << endl;cout << xxj << endl;cout << bozhu << endl;//const修飾的字符串沒法修改cout << a << endl;cout << b << endl;cout << c << endl;++b;//因為本質是同一塊空間里的同一個數據,一變全變cout << a << endl;cout << b << endl;cout << c << endl;return 0;
}
?
4.引用的使用
引用主要被用于引用傳參和做返回值時減少拷貝提高效率,和改變引用對象同時改變被引用對象(功能類似指針)在c++中大部分地方我們用引用代替指針,但是少部分地方任然離不開指針(比如鏈表,因為引用無法改變指向)。
歸根結底是因為引用對和被引用對象公用同一空間 。
4.1引用傳參
void Swap(int* rx, int* ry)
{int tmp = *rx;*rx = *ry;*ry = tmp;
}void Swap(int& rx, int& ry)
{int tmp = rx;rx = ry;ry = tmp;
}
swap是典型的傳址調用函數,可以用傳引用代替。
4.2傳引用返回
int& func1()
{int ret = 0;return ret;
}
int main()
{int& x = func1();cout << x << endl;return 0;
}
ret在函數棧幀銷毀時,空間已經被系統回收,該空間是否被覆蓋(被用于存放其他內容)是未知的,取決于編譯器,該函數的返回值是一個ret的一個引用,可以理解為系統給了一個臨時的引用變量int& tmp = ret,而引用x又對tmp進行引用,也就是說x和被銷毀的ret公用一個空間,這是危險的,畢竟我們不知道ret被銷毀后,原空間是什么狀態。
運行結果:
int& func1()
{int ret = 0;return ret;
}
int& fun2()
{int y = 123;return y;
}
int main()
{int& x = func1();cout << x << endl;fun2();cout << x << endl;return 0;
}
?當我們創建于func1幾乎相同的,在vs環境中,編譯器將原來用于func1的函數棧幀空間分配給func2,導致原來局部變量ret使用的空間被覆蓋,此時再通過別名來訪問這個空間,就會發現期望的x值已經發生改變。
上述情況是基于被引用對象隨著函數棧幀銷毀而銷毀的情況,這種情況不推薦使用傳引用返回,那么反之,當被引用對象不會隨著函數棧幀的銷毀而銷毀時,傳引用返回的使用就會使函數更加便捷和靈活,我們推薦使用傳引用返回。
對于順序表中,查找和修改指定位置的函數,利回就用傳引用返能合二為一
這時SLat函數獨自就能完成讀寫的操作。?
5.const引用(在引用的定義前用const修飾)
被const修飾的對象具有常性,只能讀,不能寫,也就是訪問權限縮小(一般權限的放大縮小是對引用和指針來說的)
對于const修飾的對象,必須用const引用?
對于普通對象,const引用也能引用
這是因為,訪問權限在引用的過程中只能縮小不能放大。
5.1對于引用
int main()
{const int a = 0;int& ra = a;return 0;
}
? ? ? ?這里就會報錯,權限被放大了。
5.2對于指針
int main()
{const int a = 0;int& ra = a;int b = 0;const int* p = &b;int* p2 = p;return 0;
}
指針的訪問權限被放大,所以報錯。(這里多提一點,被const修飾的指針,是它指向的變量具有常性,而不是指針本身具有常性)。
綜上所述,我們可以知道,在用引用傳參是盡量加上const,這樣不管被引用對象是否被const修飾,都可以進行傳參。
5.3類型轉換中的常性
和函數返回時,產生臨時變量一樣,類型轉換也會產生臨時變量。
產生的臨時變量為指定的類型且具有常性的。而跨類型引用本質上是對臨時變量的引用
int main()
{int i = 0;double& ri = i;int i = 0;const double& ri = i;
}
這里的引用,本質上是對具有常性的double類型的臨時變量的引用。
6.引用&指針
- 語法概念上,引用是給一個變量取別名,不開新空間,指針是直接創建一個指針變量來存地址,需要開辟空間。
- 語法上,引用在定義時就要初始化,指針在語法上不強求。
- 引用一旦確定被引用對象就不能更改,指針可以不斷改變指向的對象。
- 引用可以直接訪問被引用對象,而指針需要解引用。
- sizeof的含義不同,引用是被引用對象的類型大小,指針是地址所占字節個數,32位是4,64位是8。
- 指針很容易出現野指針問題,引用相對安全一些。
二者在實踐中有重疊性,但又各有千秋,它們相輔相成,互相不可完全替代。
總結
基本概念
引用是為變量創建的別名,與被引用變量共享內存空間。一個變量可擁有多個引用
核心特性
1. 必須初始化
2. 可多級引用(一個變量多個別名)
3. 一旦綁定實體后不可更改引用對象
主要用途
1. 函數參數:替代指針實現傳址調用,更安全簡潔
2. 返回值:避免拷貝開銷,但需注意返回局部變量引用的風險
const引用
遵循"權限不放大"原則:const對象必須用const引用,普通對象可用const引用
類型轉換時會生成具有常性的臨時變量
與指針對比
1. 內存:引用不占額外空間,指針需要存儲地址
2. 安全性:引用更安全,不存在野引用問題
3. 靈活性:指針可重定向,引用一旦綁定不可更改
4. 訪問方式:引用直接訪問,指針需解引用
本質區別:引用是語法層面的別名機制,指針是底層的內存地址操作。兩者在C++中互補使用,各有適用場景