C++ 中 new 並非單一構造,而是包含三種截然不同的機制,分別負責「記憶體配置」與「物件建構」的不同階段。理解三者差異,是掌握 C++ 記憶體管理與自訂配置器的基石。
功能:配置記憶體 + 呼叫建構函數初始化物件。
Emp* e1 = new Emp; // 相當於:
// 1. operator new(sizeof(Emp)) 配置原始記憶體
// 2. 在該記憶體上呼叫 Emp::Emp() 建構函數
對應釋放:delete e1;(呼叫析構函數 + operator delete 釋放記憶體)。
功能:僅配置原始記憶體,不呼叫建構函數。回傳 void*,需手動轉型。
Emp* e2 = static_cast<Emp*>(operator new(sizeof(Emp)));
// 此時 e2 指向未初始化的記憶體區塊
常用於:自訂記憶體池、配置器實作、需要精確控制物件生命週期的場合。
功能:在已配置好的記憶體上呼叫建構函數(含複製/移動建構),不配置記憶體。
new (static_cast<void*>(e2)) Emp(*e1); // 在 e2 記憶體上以 e1 為來源複製建構
語法:new (address) Type(args...)。
對應釋放:手動呼叫析構函數 e2->~Emp();,再以 operator delete(e2); 釋放記憶體。
// Emp.h
class Emp {
public:
Emp(); // 輸出 "Emp..."
Emp(const Emp& other); // 輸出 "Copy Emp..."
~Emp(); // 輸出 "~Emp..."
};
// main.cpp
int main() {
// 1. new operator:配置 + 建構
Emp* e1 = new Emp; // 輸出: Emp...
// 2. operator new:僅配置
Emp* e2 = static_cast<Emp*>(operator new(sizeof(Emp))); // 無輸出
// 3. placement new:在 e2 上以 e1 為來源複製建構
new (static_cast<void*>(e2)) Emp(*e1); // 輸出: Copy Emp...
// 正確釋放順序
e2->~Emp(); // 手動呼叫析構函數,輸出: ~Emp...
operator delete(e2); // 僅釋放記憶體
delete e1; // 正常 delete:析構 + 釋放
}
| 形式 | 配置記憶體 | 呼叫建構函數 | 典型用途 |
|---|---|---|---|
new Type | 是 | 是 | 一般物件建立 |
operator new(size) | 是 | 否 | 自訂配置器、記憶體池 |
new (ptr) Type(args) | 否 | 是 | 物件池、共享記憶體、嵌入式系統 |
operator new 可被重載(全域或類別內),支援自訂對齊、記憶體追蹤等進階需求。std::vector)內部即大量運用 placement new 實作 emplace_back 等高效插入操作。