std::allocator 提供兩個關鍵操作:
allocate(n):僅配置原始記憶體(未建構物件)。construct(ptr, args...):在已配置記憶體上就地建構物件(呼叫建構函式)。為什麼不合併成一步?分離有何意義?
vector 擴容時,必須先配置新記憶體,再將舊元素移動/複製建構到新區塊,最後解構舊元素並釋放舊記憶體。若配置即建構,無法支援「未初始化記憶體」這一中間狀態。int、double 等純資料型別,「建構」是空操作。分離後容器可統一介面,避免不必要的函式呼叫開銷。construct 失敗時,僅對已成功建構的物件呼叫 destroy,再統一 deallocate,邏輯更清晰。// 1. 空間不足時
pointer new_start = alloc.allocate(new_capacity); // 僅配置原始記憶體
// 2. 移動/複製建構現有元素
for (size_t i = 0; i < size; ++i)
alloc.construct(new_start + i, std::move(old_start[i]));
// 3. 建構新元素
alloc.construct(new_start + size, value);
// 4. 解構舊元素
for (size_t i = 0; i < size; ++i)
alloc.destroy(old_start + i);
// 5. 釋放舊記憶體
alloc.deallocate(old_start, old_capacity);
allocator 將「取得記憶體」與「初始化物件」解耦,正是為了滿足 C++ 物件模型中建構/解構語意、異常安全與容器高效能的核心需求。這是 STL 設計精髓之一,深入理解有助於撰寫高效、正確的自訂容器或記憶體管理器。