指標是 C/C++ 中最強大也最讓初學者頭痛的概念。本文用「儲物箱與鑰匙」的生活化比喻,直觀解釋指標的本質、指標變數宣告、賦值、多重指標以及函數參數傳遞的差異,幫助讀者建立正確心智模型。
int *p; 相當於建立一個只能放鑰匙的小儲物箱(4 bytes)P1 打開 A 和 B,將 A 所有物品搬到 B
// 程式對應:
void MyMethod(MyStruct B) { ... } // 參數為物件實體
MyStruct A;
MyMethod(A); // 整個 A 複製到 B(堆疊上)
// 優點:A、B 完全獨立,互不影響
// 缺點:耗時、佔記憶體、大型物件效能差
P1 只打開 B,把 A 的鑰匙放進 B
// 程式對應:
void MyMethod(MyStruct *B) { ... } // 參數為指標
MyStruct A;
MyMethod(&A); // 只傳遞 A 的位址(4 bytes)
// 優點:極快、省記憶體、可修改原物件
// 缺點:多方持有鑰匙時,一方修改會影響其他人
typedef struct { int x, y; float abc; } MyStruct;
void MyMethod(MyStruct B) { /* 操作 B */ }
MyStruct A = {1,2,3.0f};
MyMethod(A); // 複製 A 所有成員到堆疊參數 B
void MyMethod(MyStruct *B) { /* 操作 *B */ }
MyStruct A = {1,2,3.0f};
MyMethod(&A); // 只傳 &A(4 bytes),B 指向 A
p 存放位址 → 該位址存放另一位址 → 該位址存放真正資料*,就多一層「儲物箱存鑰匙」int x = 1234;
int *p = (int*)x; // 將 1234 當作記憶體位址!
// p 現在指向位址 0x4D2,解參考會導致未定義行為
警告:除非極度確定(如嵌入式硬體暫存器映射),否則嚴禁此用法。
| 情境 | 建議方式 | 理由 |
|---|---|---|
| 小型資料(int、float 等) | 傳值 | 複製成本極低,語意清晰 |
| 大型結構體/類別,唯讀 | const 參考 (const T&) | 避免複製,防止修改 |
| 大型結構體/類別,需修改 | 參考 (T&) 或指標 (T*) | 避免複製,允許修改 |
| 多型基類指標/參考 | 基類指標/參考 | 支援動態繫結 |
| 選擇性參數(可為空) | 指標 (T*) | 可傳 nullptr 表示無值 |