C++ new/delete 將「記憶體配置」與「物件構造/解構」綁定。STL 容器(如 vector)為了效率,需分離這兩步驟:預先配置大塊記憶體,按需在上面構造物件;擴容時只移動/構造,不重新配置每個元素的記憶體。std::allocator 正是這層抽象。
| allocator 介面 | 語義 | 底層對應操作 |
|---|---|---|
allocate(n) | 配置 n 個 T 的原始記憶體 | operator new[](n * sizeof(T)) |
deallocate(p, n) | 釋放原始記憶體 | operator delete[](p) |
construct(p, args...) | 在 p 處構造 T 物件 | new (p) T(args...) (placement new) |
destroy(p) | 解構 p 處的 T 物件 | p->~T() (顯式呼叫解構函數) |
void* operator new(size_t):僅配置記憶體(類 malloc)void* operator new(size_t, void* ptr):placement new,在指定位置構造物件,不配置記憶體new (ptr) T(args):語法糖,呼叫 placement new + 建構子template <class T>
void Vector<T>::push_back(const T& val) {
if (first_free == end) reallocate(); // 空間不足則擴容
alloc.construct(first_free, val); // 在備妥記憶體上構造
++first_free;
}
template <class T>
void Vector<T>::reallocate() {
ptrdiff_t size = first_free - elements;
ptrdiff_t newCap = 2 * max(size, 1);
T* newData = alloc.allocate(newCap); // 1. 配置新記憶體
uninitialized_copy(elements, first_free, newData); // 2. 搬移並構造舊元素
// 3. 逆序解構舊元素
for (T* p = first_free; p != elements; )
alloc.destroy(--p);
// 4. 釋放舊記憶體
if (elements) alloc.deallocate(elements, end - elements);
// 5. 更新指標
elements = newData;
first_free = elements + size;
end = elements + newCap;
}
uninitialized_copy(first, last, dest) 在未初始化記憶體上以拷貝建構子構造元素,避免 dest 預設構造的開銷。底層逐個呼叫 alloc.construct(dest++, *src++)。
template <class T>
class allocator {
public:
T* allocate(size_t n) {
return static_cast<T*>(::operator new[](n * sizeof(T)));
}
void deallocate(T* p, size_t n) {
::operator delete[](p);
}
template <class... Args>
void construct(T* p, Args&&... args) {
::new ((void*)p) T(std::forward<Args>(args)...);
}
void destroy(T* p) {
p->~T();
}
};
std::vector/std::allocator,無需手動管理deallocate 第二參數必須與 allocate 時相同;destroy 不釋放記憶體;placement new 無對應的 placement delete,解構後需手動 deallocate