| 類別 | 語法 | 本質 | 可否重載 | 自動建構 |
|---|---|---|---|---|
| new 運算子 | new T(args) | 語言關鍵字 | 否 | 是 |
| operator new | operator new(sz) | 函式(可重載) | 是 | 否 |
| Placement new | new (ptr) T(args) | operator new 重載形式 | 是(標準庫提供) | 是 |
string* ps = new string("hello");
// 編譯器展開為:
void* raw = operator new(sizeof(string)); // 1. 配置原始記憶體
string* ps = static_cast<string*>(raw); // 2. 型別轉換
ps->string::string("hello"); // 3. 呼叫建構函式(編譯器內部語法)
void* operator new(size_t sz) {
if (void* p = malloc(sz)) return p;
throw std::bad_alloc();
}
void* operator new[](size_t sz) { return operator new(sz); }
class Widget {
public:
void* operator new(size_t sz) { return pool_.alloc(sz); }
void operator delete(void* p) noexcept { pool_.free(p); }
// 陣列版
void* operator new[](size_t sz) { return pool_.alloc(sz); }
void operator delete[](void* p) noexcept { pool_.free(p); }
};
void* operator new(size_t sz, std::align_val_t al) {
void* p = std::aligned_alloc(static_cast<size_t>(al), sz);
if (!p) throw std::bad_alloc();
return p;
}
#include <new> // 必須包含
// 形式 1:指定位址
char buf[sizeof(Widget)];
Widget* pw = new (buf) Widget(); // 在 buf 建構
// 形式 2:帶初始化引數
int val = 42;
int* pi = new (&val) int(99); // 覆寫 val 為 99
// 形式 3:陣列 placement new(C++20)
alignas(Widget) char buf[N * sizeof(Widget)];
Widget* arr = new (buf) Widget[N]; // 建構陣列
void* operator new(size_t, void* ptr) noexcept { return ptr; }
void* operator new[](size_t, void* ptr) noexcept { return ptr; }
不配置記憶體,直接回傳指定位址;建構失敗(拋出例外)時不會呼叫對應 operator delete,必須手動解構。
std::allocator::construct() 內部使用 placement newnew (std::align_val_t(64)) Widget(C++17)| 模式 | 行為 | 適用場景 |
|---|---|---|
| 擲出例外(預設) | throw std::bad_alloc | 一般應用 |
| nothrow | new (std::nothrow) T 失敗回傳 nullptr | 無例外環境、嵌入式 |
| 自訂 new_handler | std::set_new_handler() 設定回呼嘗試釋放記憶體 | 記憶體緊張時自救 |
operator new 函式std::make_unique、std::make_shared、std::vector、std::stringstd::allocator 或 std::pmr::polymorphic_allocator 注入容器掌握 new 的三重身分與生命週期,才能在需要極致效能、特殊記憶體模型時,正確駕馭 C++ 底層機制。