術語釐清
- 形參:函數定義/聲明中的參數,作為「佔位符」接收實參。
- 實參:函數調用時實際傳入的變數/表達式/值。
三種傳遞機制對比
| 機制 | 語法 | 記憶體行為 | 能否修改實參值 | 典型用途 |
| 傳值 |
void f(int x) |
在棧上建立副本,獨立記憶體 |
否 |
只讀輸入、小型結構體 |
| 傳指標 |
void f(int *p) |
傳遞地址值,函數內透過解引用訪問原變數 |
是(*p = ...) |
修改呼叫端變數、大型結構、輸出參數 |
| 傳引用 |
void f(int &r) (C++ only) |
實參的別名,編譯層面綁定同一記憶體 |
是(r = ...) |
C++ 慣用、運算子多載、避免拷貝 |
代碼驗證:交換兩數
// 1. 傳值 —— 失敗
void swap_val(int x, int y) { int t=x; x=y; y=t; }
int a=5, b=6; swap_val(a,b); // a=5, b=6
// 2. 傳指標 —— 成功
void swap_ptr(int *x, int *y) { int t=*x; *x=*y; *y=t; }
swap_ptr(&a, &b); // a=6, b=5
// 3. 傳引用 —— 成功
void swap_ref(int &x, int &y) { int t=x; x=y; y=t; }
swap_ref(a, b); // a=5, b=6 (再換回)
進階:指標 vs 引用的本質差異
void f1(int *p) { p = nullptr; } // 只改區域副本 p
void f2(int *&p) { p = nullptr; } // 改變實參指標指向
void f3(int &r) { r = 42; } // 改變實參值
// r 不能重新綁定:int &r2 = r; // r2 也是原變數別名
- 指標是「存地址的變數」,可改指向、可為空、需解引用。
- 引用是「別名」,初始化後不可重綁、不可為空、語法像直接操作變數。
常見誤區
- 以為傳指標能改指標本身:
void f(int *p) { p = &other; } 只改副本,呼叫端指標不變。
- 混淆
const int* 與 int* const:前者限制所指內容不可改,後者限制指標本身不可改。
- C++ 傳大型物件未加
const &:觸發昂貴拷貝建構函數。
最佳實踐建議
- **輸入參數**:基本型別傳值,大型物件
const T&。
- **輸出/輸入輸出參數**:C 用
T*,C++ 用 T&(或 T* 配合 not_null)。
- **需改變指標指向**:C 用
T**,C++ 用 T*&。
- **避免
void*** 除非泛型介面(如 qsort、線程啟動)。