初學者常困惑 new 與直接定義物件的差別。本文從記憶體模型、生命週期、效能、介面設計四維度對比,給出選擇指引。
| 特性 | new Type() (堆積) | Type obj; (堆疊) |
|---|---|---|
| 記憶體區域 | Heap(自由存儲區) | Stack(函式幀) |
| 生命週期 | 手動 delete 釋放 | 離開作用域自動析構 |
| 指標/參考 | 回傳指標,可跨函式傳遞、儲存 | 僅限當前作用域,傳參需用參考/指標 |
| 大小限制 | 受限於虛擬記憶體(GB 級) | 受限於堆疊大小(預設 1-8 MB) |
| 配置速度 | 較慢(尋找空閒區塊、同步鎖) | 極快(指標遞減) |
| 釋放速度 | 較慢(合併區塊、同步鎖) | 零成本(指標遞增) |
| 例外安全 | 需 RAII/智慧指標管理 | 天然例外安全 |
for (...) { Widget w; ... }new + shared_ptr/unique_ptr。std::vector reserve、自定義 allocator)。new 回傳 void*,配對 delete 匯出函式。class Test { public: int a; };
void foo() {
Test obj; // 自動配置、自動析構
obj.a = 42;
} // obj 此處自動析構,零洩漏風險
#includestd::unique_ptr create() { return std::make_unique (); // C++14 } void bar() { auto p = create(); // 擁有權轉移 p->a = 100; } // 離開作用域自動 delete
Test* p = new Test(); p->a = 10; // ... 使用 ... delete p; // 必須配對,否則洩漏 p = nullptr;
class Best { public: int b; };
class Test { public: int a; };
Test* transform(Best* in) {
Test* out = new Test();
out->a = in->b;
return out; // 呼叫端負責 delete
}
Type* p = nullptr; 僅宣告指標,**未配置記憶體**,不可直接 p->member。new 未 delete → 記憶體洩漏(工具:Valgrind、Visual Studio CRT 偵測)。new/delete 若執行期庫不一致 → 堆積損壞(參考 malloc/free 失敗條目)。預設用堆疊 + RAII;需動態生命週期、多型、大型物件才用堆積,並務必搭配智慧指標。手動 new/delete 僅存在於 legacy 代碼或 C 介面邊界。