STL 容器與演算法分離,記憶體管理同樣抽象為 Allocator。將配置策略獨立,容器得以專注資料結構邏輯,同時支援:
malloc/free)template <class T> class allocator {
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
template <class U> struct rebind { typedef allocator<U> other; };
// ...
rebind 讓容器從 allocator<T> 取得 allocator<Node>,實現節點配置。
| 成員函式 | 語意 |
|---|---|
pointer allocate(size_type n, const void* hint = 0) | 配置 n 個 T 的原始記憶體,hint 提供區域性建議 |
void deallocate(pointer p, size_type n) | 歸還先前配置的區塊,n 必須與 allocate 時相同 |
size_type max_size() const | 理論最大可配置元素數 |
void construct(pointer p, const T& val) { ::new((void*)p) T(val); }
void destroy(pointer p) { p->~T(); }
分離「原始記憶體取得」與「物件初始化」,支援 vector::reserve() 僅配置不建構。
頻繁小區塊 new/delete 導致:
malloc()/free()_malloc_alloc_oom_handler 嘗試釋放備用記憶體核心資料結構:
配置流程:
index = (bytes + 7) / 8 - 1refill() 向記憶體池取 20 區塊(可配置)chunk_alloc() 向系統 malloc() 申請大塊釋放流程:
| 特性 | SGI 二級配置器 | Linux Slab |
|---|---|---|
| 應用層級 | 使用者空間 | 核心空間 |
| 物件大小 | 8~128 bytes 固定級距 | 任意大小,動態建立 cache |
| 着色/對齊 | 8 bytes 對齊 | 硬體快取行着色、NUMA 感知 |
| 回收機制 | 不主動歸還系統 | slab 空閒時可歸還頁框 |
template <class T, size_t PoolSize = 4096>
class PoolAllocator {
alignas(T) char pool_[PoolSize];
T* free_list_ = nullptr;
size_t used_ = 0;
public:
using value_type = T;
PoolAllocator() noexcept = default;
template <class U> PoolAllocator(const PoolAllocator<U>&) noexcept {}
T* allocate(size_t n) {
if (n != 1) throw std::bad_alloc();
if (free_list_) {
T* p = free_list_;
free_list_ = *reinterpret_cast<T**>(free_list_);
return p;
}
if (used_ + sizeof(T) <= PoolSize) {
return reinterpret_cast<T*>(pool_ + used_ += sizeof(T));
}
throw std::bad_alloc();
}
void deallocate(T* p, size_t) noexcept {
*reinterpret_cast<T**>(p) = free_list_;
free_list_ = p;
}
};
std::allocator_traits 與 C++17 std::pmrallocator_traits 統一介面、提供預設實作,容器不再直接依賴 Allocator 成員std::pmr::polymorphic_allocator + memory_resource 實現執行期多態配置策略,取代靜態模板參數new (std::align_val_t)、std::allocator::allocate(size_t, size_t alignment) 支援對齊需求Allocator 是 STL 「政策基底類別」設計哲學的典範:將變動點(配置策略)參數化,讓容器在零開銷抽象下獲得極大靈活性。理解兩級配置器原理,不僅能優化高頻小物件場景,更能洞悉現代記憶體管理的核心權衡——碎片 vs 開銷、延遲 vs 吞吐、通用 vs 專用。