malloc/free 是 C 標準庫函式,new/delete 是 C++ 運算子。兩者皆管理動態記憶體,但語意、行為、適用場景截然不同。本文從物件生命週期、型別安全、效能、混用風險四大維度深度剖析。
| 維度 | malloc/free | new/delete |
|---|---|---|
| 性質 | 函式 | 運算子(可重載) |
| 型別安全 | 回傳 void* 需強制轉型 | 回傳具型別指標,編譯期檢查 |
| 物件建構 | 不呼叫建構函式 | 自動呼叫建構函式 |
| 物件解構 | 不呼叫解構函式 | 自動呼叫解構函式 |
| 失敗處理 | 回傳 NULL | 拋出 std::bad_alloc |
| 陣列支援 | 手動計算大小 | new T[n] / delete[] |
| 記憶體來源 | 堆 | 堆(預設實作呼叫 malloc) |
class Obj {
public:
Obj() { puts("建構"); }
~Obj() { puts("解構"); }
void Init() { puts("手動初始化"); }
void Destroy() { puts("手動清理"); }
};
// malloc 版:需手動管理生命週期
void UseMalloc() {
Obj* p = (Obj*)malloc(sizeof(Obj));
p->Init(); // 手動初始化
// ... 使用
p->Destroy(); // 手動清理
free(p);
}
// new 版:語言層級保證
void UseNew() {
Obj* p = new Obj; // 自動建構
// ... 使用
delete p; // 自動解構 + 釋放
}
malloc/free 管理記憶體,雙方邊界必須對應malloc/free 效能略優(無例外處理開銷)std::allocator 內部仍可能委派給 mallocfree(new Obj):漏呼解構函式 → 資源洩漏delete malloc(100):行為未定義(雖然某些實作碰巧能跑)
int* p1 = (int*)malloc(10 * sizeof(int));
free(p1); // 正確
int* p2 = new int[10];
delete[] p2; // 必須用 delete[],否則僅呼叫第一個元素解構函式
delete p2; // 錯誤!未定義行為
void* operator new(size_t sz) {
void* p = malloc(sz);
if (!p) throw std::bad_alloc();
return p;
}
void operator delete(void* p) noexcept { free(p); }
// 類別專屬
class Foo {
static void* operator new(size_t sz) { /* 專用記憶池 */ }
static void operator delete(void* p) { /* 回收至記憶池 */ }
};
std::unique_ptr/shared_ptr + make_unique/make_sharedstd::vector/string 替代手動陣列管理new 配 delete,new[] 配 delete[],malloc 配 free,絕不交叉Allocator 概念,配合 std::allocate_shared