一、基本概念:先搞懂“是什麼”¶
在C++中,引用(Reference)和指針(Pointer)都與“變量的地址”或“別名”相關,但本質截然不同:
-
引用:是變量的別名,它與原變量共享同一塊內存空間,必須在定義時綁定到一個已存在的對象,且一旦綁定就無法再指向其他對象。
比如:int a = 10; int& ref = a;這裏ref就是a的別名,修改ref就等於修改a。 -
指針:是一個存儲地址的變量,它可以指向某個變量的內存地址,也可以爲
nullptr(表示不指向任何對象)。
比如:int a = 10; int* ptr = &a;這裏ptr存儲的是a的地址,通過*ptr可以訪問a的值。
二、核心區別:這5點必須分清¶
| 對比項 | 引用(Reference) | 指針(Pointer) |
|---|---|---|
| 語法形式 | 定義時用 &,無額外空間(如 int& ref = a;) |
定義時用 * 和 &,本身佔用內存(如 int* ptr = &a;) |
| 是否爲空 | 不能爲 nullptr(必須綁定對象) |
可以爲 nullptr(表示未指向任何對象) |
| 初始化 | 必須在定義時初始化(如 int& ref = a;) |
可先不初始化(但通常需賦值合法地址或 nullptr) |
| 可變性 | 綁定後不可再指向其他對象(一生只能綁定一個) | 可隨時修改指向(如 ptr = &b;) |
| 解引用 | 直接使用(如 ref = 20;) |
需用 * 解引用(如 *ptr = 20;) |
三、關鍵細節:初學者常犯的錯誤¶
-
引用不能單獨存在
引用必須綁定到對象,不能像指針一樣“懸空”。比如:int& ref;是錯誤的,必須寫成int& ref = a;。 -
指針可“空”,引用不可
指針可以是nullptr(表示無有效指向),例如int* ptr = nullptr;;而引用若爲nullptr會直接報錯。 -
大小不同
- 引用的大小與被引用類型相同(如int&大小是int的大小,4字節)。
- 指針的大小固定(32位系統4字節,64位系統8字節),與指向的類型無關。
四、使用場景:什麼時候用引用?什麼時候用指針?¶
優先用引用的場景:
1. 函數參數:避免大對象拷貝(如 void print(const string& s))。引用傳遞不會複製整個對象,效率更高。
2. 返回對象:避免返回大對象時的拷貝(如 string& getStr())。
3. 數組/容器別名:給數組或容器取別名(如 vector<int>& v = vec;)。
4. 重載運算符:如 string& operator[](int index)(類似C++標準庫的數組訪問)。
優先用指針的場景:
1. 動態內存管理:需手動分配/釋放內存(如 int* p = new int[10];)。
2. 需修改指針指向:比如函數需改變指針的指向(如 void swap(int* a, int* b))。
3. 返回空指針表示失敗:若函數可能無有效結果,用指針返回 nullptr(如 Node* findNode(int key))。
4. 數組或容器的動態訪問:通過指針遍歷數組(如 int* p = arr; p++;)。
五、代碼示例:用起來更直觀¶
例1:引用與指針的修改對比
int a = 10;
int& ref = a; // ref是a的別名
int* ptr = &a; // ptr指向a的地址
// 修改引用/指針,等價於修改原變量a
ref = 20; // 等價於 a = 20
*ptr = 30; // 等價於 a = 30
cout << a << endl; // 輸出:30(ref和ptr都修改了a)
例2:引用與指針的不可變性
int x = 10, y = 20;
int& ref = x; // ref只能綁定x
ref = y; // 合法:ref=20(修改x的值爲20)
// ref = &y; // 錯誤:引用不能重新指向其他對象!
int* ptr = &x;
ptr = &y; // 合法:ptr現在指向y
*ptr = 30; // 修改y的值爲30
cout << y << endl; // 輸出:30
六、總結:一句話記住¶
- 引用:變量的“別名”,簡單、安全,適合直接訪問對象(避免拷貝)。
- 指針:存儲地址的“變量”,靈活但需手動管理(如空指針、內存釋放),適合動態場景。
新手建議:優先用引用(安全、簡潔),僅在必須處理空值或動態內存時用指針。
(注:本文代碼基於C++11及以上標準,需注意編譯器對引用的支持)