C++ 記憶體管理是面試與實戰高頻考點。本文系統梳理指標參數傳遞機制、動態配置正確姿勢、野指標成因與防禦、new/delete 與 malloc/free 本質差異。
void GetMemory(char* p, int n) {
p = malloc(n); // 僅修改區域副本 _p,呼叫端 p 不變
}
char* str = NULL;
GetMemory(str, 100); // str 仍為 NULL → strcpy 崩潰
原因:參數傳值,編譯器建立副本 _p = p。函數內修改 _p 指向新記憶體,原 p 不變。
void GetMemory2(char** p, int n) { *p = malloc(n); }
char* str = NULL;
GetMemory2(&str, 100); // 傳址,修改 *p 即修改 str
char* GetMemory3(int n) { return malloc(n); }
char* str = GetMemory3(100);
void GetMemory4(char*& p, int n) { p = malloc(n); } // 參考即別名
GetMemory4(str, 100);
char* GetString() {
char p[] = "hello"; // 區域陣列在棧上
return p; // 警告:回傳區域變數位址
}
// 呼叫端拿到的是已失效記憶體 → 垃圾值
malloc/new 的堆記憶體、靜態/全域變數、字串常值char* p = "hello"; 位於唯讀資料段,生命週期全程,但不可修改| 成因 | 範例 | 防禦 |
|---|---|---|
| 未初始化 | int* p; | 宣告即初始化:int* p = nullptr; |
| 釋放後未置空 | free(p); // p 成野指標 | free(p); p = nullptr; |
| 超出作用域 | { int a; p=&a; } p->func(); | 勿回傳/儲存區域物件位址,用智慧指標管理生命週期 |
| 特性 | new/delete | malloc/free |
|---|---|---|
| 本質 | 運算子(編譯器支援) | 標準庫函數 |
| 建構/解構 | 自動呼叫 constructor/destructor | 不支援,需手動 Initialize()/Destroy() |
| 型別安全 | 自動推導型別、回傳正確指標 | 回傳 void* 需強制轉型 |
| 失敗處理 | 拋出 bad_alloc 例外 | 回傳 NULL |
| 記憶體不足自訂處理 | set_new_handler | 無標準機制 |
| 陣列支援 | new T[n] / delete[] | 手動計算 n*sizeof(T) |