| 函數 | 作用 |
allocate(n) | 分配 n 個 T 對象的未初始化內存 |
deallocate(p, n) | 釋放 p 指向的 n 個對象內存 |
construct(p, args) | 在 p 處構造 T 對象(調用構造函數) |
destroy(p) | 調用 p 處對象的析構函數 |
模擬 vector::push_back 核心邏輯
template <class T>
class SimpleVector {
static allocator<T> alloc;
T* elements; // 數組首地址
T* first_free; // 首個空閒位置
T* end; // 分配內存末尾
void push_back(const T& val) {
if (first_free == end) reallocate(); // 擴容
alloc.construct(first_free, val); // 原地構造
++first_free;
}
void reallocate() {
size_t newCap = max(2 * (first_free - elements), size_t(1));
T* newData = alloc.allocate(newCap);
// 移動現有元素(C++11 移動語義)
uninitialized_copy(make_move_iterator(elements),
make_move_iterator(first_free), newData);
// 銷毀舊元素
for (T* p = first_free; p != elements; ) alloc.destroy(--p);
// 釋放舊內存
if (elements) alloc.deallocate(elements, end - elements);
// 更新指針
elements = newData;
first_free = elements + (first_free - elements);
end = elements + newCap;
}
};
方案二:operator new / delete + placement new
標準庫提供全局 operator new(size_t) 和 operator delete(void*) 分配/釋放原始字節內存。配合 placement new 實現原地構造:
// 分配原始內存(相當於 alloc.allocate)
T* raw = static_cast<T*>(operator new[](sizeof(T) * n));
// 在已分配內存上構造對象(相當於 alloc.construct)
new (raw + i) T(args); // placement new 語法
// 顯式調用析構函數(相當於 alloc.destroy)
(raw + i)->~T();
// 釋放原始內存(相當於 alloc.deallocate)
operator delete[](raw);
placement new 關鍵優勢
- 支持任意構造函數(allocator::construct 僅支持拷貝構造)
- 避免臨時對象拷貝開銷(對於禁用拷貝的類型至關重要)
- 無異常安全額外開銷
標準庫輔助算法
uninitialized_copy:拷貝構造到未初始化內存
uninitialized_fill:填充構造到未初始化內存
uninitialized_move:移動構造(C++17)
最佳實踐總結
- 優先使用
std::allocator:類型安全、異常安全、符合 STL 慣例
- 需要精細控制或特殊構造時使用
placement new
- 嚴格配對:
allocate/construct 與 destroy/deallocate
- 內存池場景考慮對齊要求(
alignas / std::aligned_storage)
- 上一篇文章: 優化篩法求素數:基於 6k±1 規律的 C++ 高效實現
- 下一篇文章: HDU 2795 Billboard:線段樹維護廣告牌剩餘寬度的經典應用
Copyright ©
程式碼之家 All Rights Reserved