參考是變數的別名,非獨立物件。理解其「非物件」本質,能避開位址操作、重新繫結、陣列參考等常見誤區。本文以實例代碼驗證核心行為。
int a = 10;
int& r = a;
std::cout << r << " | " << a << std::endl; // 10 | 10
std::cout << &r << " | " << &a << std::endl; // 相同位址
// 關鍵:C++ 無法取得參考本身的位址
// &r 即為 &a,編譯器直接替換
int a = 10, b = 20;
int& r = a; // 初始化綁定 a
r = b; // 這是「指派」,非重新繫結!
// 相當於 a = b,a 變為 20,r 仍綁定 a
std::cout << a << " | " << b << std::endl; // 20 | 20
std::cout << &r << " | " << &a << " | " << &b << std::endl; // r/a 位址相同,b 不同
鐵律:參考初始化即綁定,終生不變。`r = b` 是修改綁定目標的值,非改變綁定關係。
| 限制 | 錯誤代碼 | 原因 |
|---|---|---|
| 不可宣告 void 參考 | void& r = a; | void 為不完整型別,無實例 |
| 不可宣告參考陣列 | int& arr[10] = a; | 陣列元素需為物件,參考非物件 |
| 不可為參考取址 | &r 即為目標位址 | 參考無獨立位址 |
| 參考必須初始化 | int& r; | 無預設建構概念 |
void Swap(int& a, int& b) { int t=a; a=b; b=t; }
void Print(const BigObject& obj) { /* 僅讀,避免複製 */ }
int& GetElement(std::vector<int>& v, size_t i) {
return v[i]; // 回傳元素參考,呼叫端可修改
}
GetElement(vec, 3) = 42; // 合法:左值指派
int& BadFunc() {
int local = 10;
return local; // 編譯器警告:回傳區域變數參考
} // local 銷毀,回傳參考成懸空參考
const int& r = 10; // 字面常數 10 的壽命延伸至 r 銷毀
const std::string& s = "hello"; // 暫時 std::string 物件壽命延伸
// 僅限 const 左值參考或右值參考 (C++11)
// 非 const 參考無法綁定暫時物件
// int& r2 = 10; // 錯誤
void Process(std::string&& rval) { // 接收右值
// 可竊取資源
}
Process(std::string("temp")); // 字面值 → 右值
Process(std::move(myString)); // 左值轉右值
// 參考摺疊規則:
// T& & → T&
// T& && → T&
// T&& & → T&
// T&& && → T&&
| 現象 | 可能原因 | 排查 |
|---|---|---|
| 修改參考未影響預期變數 | 參考綁定錯誤目標 / 被遮蔽 | 檢查初始化處、列印位址對比 |
| 程式隨機崩潰 | 懸空參考 (回傳區域變數、容器重新配置失效迭代器/參考) | AddressSanitizer、審視回傳參考函數 |
| 編譯錯誤:non-const reference cannot bind | 嘗試將非 const 參考綁定暫時物件/常數 | 改為 const 參考、右值參考、或值傳遞 |
參考是「別名」,非指標、非物件。牢記:初始化即綁定、不可重繫結、無獨立位址、不可成陣列。善用 const 左值參考避免複製、右值參考實現移動語意、參考回傳支援鏈式呼叫與左值指派,是現代 C++ 高效程式設計的基石。