首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

C++ allocator 深度解析:底層記憶體管理與 STL 容器實作原理

     編輯:C++ 入門

為什麼需要 allocator?

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() (顯式呼叫解構函數)

placement new 與 operator new 區別

  • void* operator new(size_t):僅配置記憶體(類 malloc)
  • void* operator new(size_t, void* ptr):placement new,在指定位置構造物件,不配置記憶體
  • new (ptr) T(args):語法糖,呼叫 placement new + 建構子

vector::push_back 簡化實作

template <class T>
void Vector<T>::push_back(const T& val) {
    if (first_free == end) reallocate(); // 空間不足則擴容
    alloc.construct(first_free, val);    // 在備妥記憶體上構造
    ++first_free;
}

reallocate 完整邏輯

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 關鍵作用

uninitialized_copy(first, last, dest) 在未初始化記憶體上以拷貝建構子構造元素,避免 dest 預設構造的開銷。底層逐個呼叫 alloc.construct(dest++, *src++)。

allocator 實作精要

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,無需手動管理
  • 高效能/嵌入式:自訂 allocator 可減少記憶體碎片、控制對齊、使用記憶體池
  • 避坑指南:deallocate 第二參數必須與 allocate 時相同;destroy 不釋放記憶體;placement new 無對應的 placement delete,解構後需手動 deallocate
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved