首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

C++ 引用(&) 與取地址(&) 徹底區分:語法語義與實戰辨析

     編輯:C++ 入門

前言:同一符號,兩種身份

C++ 中 & 符號雙重身份讓初學者困惑:

  • 聲明中的 & → **引用宣告符** (Reference Declarator)。
  • 表達式中的 & → **取地址運算符** (Address-of Operator)。

核心口訣:**「與類型在一起是引用,與變量在一起是取址」**。

一、引用宣告符:別名綁定

int a = 10;
int& ref = a; // ref 是 a 的別名,編譯期綁定,運行期無額外存儲
ref = 20;     // 修改 a 為 20

// 函式參數傳引用:避免拷貝、修改實參
void swap(int& x, int& y) { int t=x; x=y; y=t; }

// 返回引用:延長生命週期、鏈式調用
int& get_ref() { static int v; return v; }
get_ref() = 42; // 左值引用可作左值

關鍵規則:

  • 引用**必須初始化**,且**不可重新綁定** (C++11 前無 std::reference_wrapper 等輔助)。
  • 引用不是對象,**沒有地址** (對引用取址得到的是被引用對象地址)、**沒有大小** (sizeof(ref) == sizeof(int))。
  • const 引用可綁定臨時對象/字面值/類型轉換結果:const int& r = 10; (延長臨時量生命週期)。

二、取地址運算符:指針生成器

int a = 10;
int* p = &a; // 取 a 的地址,生成指針
*p = 20;     // 解引用修改 a

// 結構體成員取址
struct S { int x; };
S s; int* px = &s.x; // 成員地址

// 多級取址
int** pp = &p; // 取指針 p 的地址

關鍵規則:

  • 只能作用於**左值** (有地址的對象):**不能**對字面值、臨時對象、右值引用結果取址。
  • 返回類型:T* (指向對象類型的指針)。
  • 可重複應用:&&a 非法,但 &*&a 合法 (等價 &a)。

三、並排對比:一眼看穿

維度引用 (& 在聲明中)取地址 (& 在表達式中)
出現位置類型聲明中,變量名前表達式中,變量/對象前
語法角色宣告符 (Declarator)一元運算符 (Operator)
結果類型引用類型 T&指針類型 T*
語義建立別名綁定獲取記憶體地址
可重新綁定否指針可指向新對象
適用對象左值、const 引用可綁右值僅左值
典型用途函式參數/返回、範圍 for、別名指針初始化、C API 互操作、觀察者模式

四、實戰辨析練習

int x = 1;
int& r1 = x;      // (1) 引用宣告:r1 綁定 x
int* p1 = &x;     // (2) 取地址:p1 指向 x
int& r2 = *p1;    // (3) 引用宣告:r2 綁定 *p1 (即 x)
int* p2 = &r1;    // (4) 取地址:對引用取址 → 取被引用對象地址 → p2 指向 x
int&& rv = 10;    // (5) 右值引用宣告 (C++11)
int* p3 = &rv;    // (6) 取地址:右值引用也是左值表達式,可取址

// 錯誤示例
int* p4 = &10;    // 錯誤:字面值無地址
int& r3 = 10;     // 錯誤:非 const 引用不可綁定右值
const int& r4 = 10; // 正確:const 引用延長臨時量生命週期

五、現代 C++ 擴展:右值引用 &&

C++11 引入 && (右值引用宣告符),支援移動語義與完美轉發:

void process(int&& x) { /* 接管臨時對象資源 */ }
process(42); // 42 是右值,綁定到 int&&
int a = 10;
process(std::move(a)); // 將左值轉為右值引用

辨析:&& 在聲明中是右值引用宣告符;在模板參數推導/轉發引用中 (T&&) 是**通用引用**,可綁定左值/右值,需配合 std::forward。

六、避坑指南

  1. 引用不是指針:無法 sizeof(ref) 得到指針大小,無法算術運算,無法置空。
  2. 返回局部變量引用是 UB:函式結束局部變量銷毀,引用懸空。
  3. 範圍 for 中用引用修改元素:for (auto& x : v) x *= 2;;只讀用 const auto& 避免拷貝。
  4. 標準庫容器插入可能導致引用失效:vector 擴容、map/set 重平衡、string SSO 狀態變化,均可能使現有引用/指針/迭代器失效。

結語

& 的雙重身份是 C++ 兼容 C 語法並引入引用機制的歷史遺產。牢記 **「類型邊是引用,變量邊是取址」**,結合左值/右值、const/非 const、聲明/表達式上下文,即可輕鬆辨析。現代 C++ 更應善用引用簡化代碼、避免拷貝、表達所有權語義,將指針保留給底層互操作與性能極致場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved