| 特性 | delete 運算子 | operator delete 函式 |
|---|---|---|
| 語法形式 | delete ptr; / delete[] arr; | void operator delete(void* ptr) noexcept; |
| 自動呼叫解構函式 | 是 | 否 |
| 可否重載 | 不可(內建) | 可(全域/類別成員) |
| 對應 new | new 運算子 | operator new 函式 |
// delete ps; 其中 ps: string*
ps->~string(); // 1. 呼叫解構函式
operator delete(ps); // 2. 釋放原始記憶體
陣列形式 delete[] arr; 會依序呼叫每個元素解構函式,再釋放整塊記憶體。
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 Widget {
public:
static void* operator new(size_t sz) { return pool_.alloc(sz); }
static void operator delete(void* p) noexcept { pool_.free(p); }
static void* operator new[](size_t sz) { return pool_.alloc(sz); }
static void operator delete[](void* p) noexcept { pool_.free(p); }
private:
static MemoryPool pool_;
};
char buffer[sizeof(Widget)];
Widget* pw = new (buffer) Widget(); // Placement new
// 正確釋放順序
pw->~Widget(); // 顯式呼叫解構函式
// 禁止:delete pw; // 錯誤!buffer 不在堆積上
// 禁止:operator delete(pw); // 錯誤!同上
Placement new 僅在既有記憶體建構物件,不配置記憶體,故無對應 delete 運算子。
new 對應 delete,new[] 對應 delete[],malloc 對應 free,placement new 對應顯式解構Base* 刪除 Derived 物件需虛解構函式delete p; p = nullptr; 防止雙重釋放與懸空指標delete nullptr 無副作用new T[10] 必須 delete[],否則未定義行為operator new 必須重載對應 operator delete| 錯誤模式 | 後果 | 偵測工具 |
|---|---|---|
| 未釋放 | 記憶體洩漏 | Valgrind, AddressSanitizer, VS CRT Debug Heap |
| 雙重釋放 | 堆積損毀、崩潰 | 同上 + _CrtSetDbgFlag |
| 使用已釋放記憶體 | 未定義行為、資料竊取 | ASan, PageHeap |
| 錯誤 delete[] | 解構函式漏呼/多呼 | 程式碼審查、靜態分析 |
std::unique_ptr、std::shared_ptr、std::vector 等 RAII 容器std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(...), fclose);new/delete 封裝在建構/解構函式內徹底理解 delete 的雙重身分與執行語意,是寫出無洩漏、無 UB、高效能 C++ 程式的基石。