malloc/free:C 標準庫函數
- 功能:申請/釋放原始字節塊,返回
void*,需強制轉型。
- 頭文件:
<stdlib.h>。
- 特點:僅管理內存,不調用構造/析構函數,不知類型、不關心對象語義。
- 可覆蓋:是普通函數,可被自定義實現替換(如內存池、檢測工具)。
- 指針運算:返回的指針可自由移動(
p+1 指向下一字節),靈活但危險。
new/delete:C++ 運算符
- 功能:分配內存 並調用構造函數;釋放前 調用析構函數。
- 類型安全:返回具體類型指針,無需轉型。
- 可重載:可全局或類級重載
operator new/delete,實現自定義分配策略(對齊、內存池、診斷)。
- 失敗行為:拋出
std::bad_alloc(或返回 nothrow 版本的 nullptr),而 malloc 返回 NULL。
對比表
| 維度 | malloc/free | new/delete |
| 性質 | 庫函數 | 運算符(編譯器內建) |
| 構造/析構 | 無 | 自動調用 |
| 返回類型 | void* | T* |
| 失敗處理 | 返回 NULL | 拋出異常 |
| 重載/覆蓋 | 可覆蓋函數 | 可重載運算符 |
| 數組支持 | 手動計算大小 | new T[n] / delete[] 自動管理 |
| 適用對象 | POD、C 結構體、原始緩衝區 | 所有 C++ 類類型(含非平凡構造/析構) |
靜態 vs 動態內存
// 靜態(編譯期確定大小,棧/數據段)
char a[10]; // 10 字節
int arr[100]; // 400 字節
// 動態(運行期確定,堆)
char* p = (char*)malloc(10);
int* q = new int[100];
- 靜態:生命週期由作用域/程序自動管理,速度快,但大小固定、大對象易棧溢出。
- 動態:大小靈活、生命週期可控,但需手動管理、有碎片化風險、分配較慢。
最佳實踐
- C++ 代碼首選 new/delete(或智能指針
unique_ptr/shared_ptr、容器 vector/string),保證構造/析構正確執行。
- 只在以下場景用 malloc/free:
① 純 C 代碼
② 需要 realloc 擴縮緩衝區
③ 分配原始字節緩衝區供 placement new 使用
④ 與 C 庫交互(如 strdup 返回的指針需 free)
- 嚴禁混用:
malloc 分配必須 free,new 必須 delete,new[] 必須 delete[],交叉使用導致未定義行為。
- 檢查返回值:
malloc 後判 NULL,new 捕獲異常或用 nothrow 版。