C++ 空间配置器allocator类

allocator类

C++中,内存分配和对象构造紧密纠缠(new),就像对象析构和回收一样(delete)。如果程序员想接管内存分配,即将内存分配和对象构造分开,对于前者,主要是分配和释放未构造的原始内存;对于后者,主要是在原始内存中构造和撤销对象。

 

分配和释放未构造的原始内存 两种方法:

  • allocator类,提供可感知类型的内存分配;
  • 标准库中的opeator new和operator delete,它们分配和释放需要大小的原始、未类型化的内存;

 

在原始内存中构造和撤销对象 不同方法:

  • allocator类定义了名为construct和destroy的成员;
  • placement new表达式,接受指向未构造内存的指针;
  • 直接调用对象的析构函数来撤销对象;
  • 算法uninitialized_fill 和 uninitialized_copy,在目的地构造对象;

 

C++的STL中定义了很多容器,容器的第二个模板参数通常为allocator类型,标准库中allocator类定义在头文件memory中,用于帮助将内存分配和对象的构造分离开来。它分配的内存是原始的、未构造的。

 

表达式 说明
allocator<T> a  定义了一个名为a的allocator对象,它可以为类型T的对象分配内存
a.allocator(n)  分配一段原始的、未构造的内存,这段内存能保存n个类型为T的对象
a.deallocate(p, n)

释放T*指针p地址开始的内存,这块内存保存了n个类型为T的对象,p必须是一个先前由allocate返回的指针,

且n必须是p创建时所要求的大小,且在调用该函数之前必须销毁在这片内存上创建的对象。

a.construct(p, t) 在T*指针p所指向内存中构造一个新元素。运行T类型的复制构造函数用t初始化该对象
a.destory(p)  运行T*指针p所指向对象的析构函数
   
uninitialized_copy(b,e,b2)

从迭代器b和e指出的输入范围中拷贝元素到从迭代器b2开始的未构造的原始内存中,该函数在目的地构造元素,而不是给它们复制。

假定由b2指出的目的地足以保存输入范围中元素的副本

uninitialized_fill(b,e,t)  将由迭代器b和e指出的范围中的对象初始化为t的副本,假定该范围是未构造的原始内存,使用复制构造函数构造对象
uninitalized_fiil_n(b,e,t,n) 将由迭代器b和e指出的范围中至多n个对象初始化为t的副本,假定范围至少为n个元素大小,使用复制构造函数构造对象

      

      
    STL都会使用allocator类来为容器分配空间,例如:

#include <memory>

template <class T> class Vector {
    public:
        Vector(): elements(0), first_free(0), end(0) {}
        void push_back(const T&);

    private:
        static std::allocator<T> alloc; // object to get raw memory
        void reallocate();  // get more space and copy existing elements
        T* elements;        // pointer to first elment in the array
        T* first_free;      // pointer to first free element in the array
        T* end;             // pointer to one past the end of the array
};

template <class T> std::allocator<T> Vector<T>::alloc;

template <class T>
void Vector<T>::push_back(const T& t) {
    if (first_free == end) {
        reallocate(); 
    }   
    alloc.construct(first_free, t); 
    first_free++;
}

template <class T>
void Vector<T>::reallocate() {
    // compute size of current array and allocate space for twice as many elements
    std::ptrdiff_t size = first_free - elements;
    std::ptrdiff_t newcapacity = 2 * (size > 1 ? size : 1); 
    T* newelements = alloc.allocate(newcapacity);

    std::uninitialized_copy(elements, first_free, newelements);

    for (T* p = first_free; p != elements; alloc.destroy(--p));

    if (elements) {
        alloc.deallocate(elements, end - elements);
    }

    elements = newelements;
    first_free = elements + size;
    end = elements + newcapacity;
}

 

      

   

 

              

             

 

posted @ 2020-02-11 08:41  如果的事  阅读(1309)  评论(0编辑  收藏  举报