首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 堆記憶體完全指南:malloc/free 與 new/delete 深度對比

     編輯:關於C++

為什麼需要堆記憶體?

  • 陣列大小必須編譯期確定(靜態/棧上分配),無法適應運行期才知曉的資料量。
  • 大型物件放棧易導致棧溢出(預設 1~8 MB)。
  • 物件生命週期需超出當前作用域(如工廠函數回傳、跨線程共享)。

C 風格:malloc / free

基本用法

#include <cstdlib>  // 或 <malloc.h>
int n; cin >> n;
int *arr = (int*)malloc(n * sizeof(int));  // 強制轉型,malloc 返回 void*
if (!arr) { /* 配失敗處理 */ }
for (int i=0; i<n; ++i) arr[i] = i;
// 使用完畢
free(arr);  // 必須成對調用,否則記憶體洩漏

關鍵特性

特性說明
不呼叫建構子/解構子僅分配原始位元組,適用於 POD 型別;類別物件需手動 placement new
可重新調整大小realloc(ptr, new_size) 保留資料擴縮記憶體
無型別安全返回 void*,需手動轉型,易出錯
失敗返回 NULL不拋異常,必須檢查返回值

C++ 風格:new / delete

基本用法

int n; cin >> n;
int *arr = new int[n];        // 分配陣列,自動呼叫預設建構子
// 使用...
delete[] arr;                 // 陣列必須用 delete[],單一物件用 delete

核心優勢

  • 型別安全:返回精確型別指標,無需轉型。
  • 自動建構/解構:逐元素呼叫建構子與解構子,支援非 POD 類別。
  • 失敗拋異常:預設拋 std::bad_alloc,可用 new (std::nothrow) 改為返回 nullptr。
  • 可重載/自定義:類別可重載 operator new/delete,實現記憶體池、診斷追蹤等。

深度對比:為什麼 C++ 專案禁用 malloc/free?

class Widget {
public:
    Widget() { cout << "ctor\n"; }
    ~Widget() { cout << "dtor\n"; }
};

void c_style() {
    Widget *w = (Widget*)malloc(sizeof(Widget));  // 僅分配記憶體,ctor 未呼叫!
    free(w);  // dtor 同樣未呼叫,資源洩漏隱患
}

void cpp_style() {
    Widget *w = new Widget();  // 分配 + ctor
    delete w;                  // dtor + 釋放
}

進階主題:記憶體對齊與 aligned_alloc / operator new

  • C++17 std::aligned_alloc、C11 aligned_alloc 支援指定對齊邊界(如 SIMD、GPU DMA 緩衝區需 64/128 bytes 對齊)。
  • C++ 可重載 static void* operator new(size_t, std::align_val_t) 實現類別級對齊控制。

現代 C++ 最佳實踐:智慧指標與容器

常見錯誤與除錯技巧

  • 配對錯誤:new[] 對 delete、malloc 對 delete —— 嚴重未定義行為。
  • 重複釋放:同一指標 free 兩次 → 堆損壞;用智慧指標自動規避。
  • 釋放後使用:delete p; p->foo(); —— 用 AddressSanitizer (ASan) 編譯選項 -fsanitize=address 快速定位。
  • 記憶體洩漏:Valgrind / Visual Studio Diagnostic Tools / Dr. Memory 定期檢測。

總結

  1. malloc/free 是 C 遺產,僅適合 POD 原始記憶體操作;C++ 專案**強烈建議**全面改用 new/delete 或更高層級封裝。
  2. new/delete 提供型別安全、建構解構自動化、異常安全、可擴展性。
  3. 現代 C++ (C++11 以降) 應以 std::unique_ptr、std::vector、std::string 為主力,**極少**直接接觸裸指標與手動釋放。
  4. 理解底層機制是為了讀懂舊代碼、編寫高效能分配器、診斷疑難雜症,而非日常開發手段。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景推薦做法避免
單一擁有權物件std::unique_ptr<T> / std::make_unique裸 new/delete
共享擁有權std::shared_ptr<T> / std::make_shared手動參考計數
動態陣列/緩衝區std::vector<T> / std::stringnew T[n] / malloc
固定大小陣列std::array<T, N> (棧上) / std::unique_ptr<T[]>VLA / malloc