C++引用與指針的區別:什麼時候用引用?

一、基本概念:先搞懂“是什麼”

在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;

三、關鍵細節:初學者常犯的錯誤

  1. 引用不能單獨存在
    引用必須綁定到對象,不能像指針一樣“懸空”。比如:int& ref; 是錯誤的,必須寫成 int& ref = a;

  2. 指針可“空”,引用不可
    指針可以是 nullptr(表示無有效指向),例如 int* ptr = nullptr;;而引用若爲 nullptr 會直接報錯。

  3. 大小不同
    - 引用的大小與被引用類型相同(如 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及以上標準,需注意編譯器對引用的支持)

小夜