c++_allocator类


目录

std::allocator::allocate

c++中的allocator类

概述

allocator用法

详解

allocate用于分配原始内存

Return value

在STL中也会用allocate类

std::allocator::allocate

(1)
pointer allocate( size_type n, const void * hint = 0 ); (until C++17)
T* allocate( std::size_t n, const void * hint); (since C++17) (deprecated) (removed in C++20)(2)
T* allocate( std::size_t n ); (since C++17) (until C++20)
[[nodiscard]] constexpr T* allocate( std::size_t n ); (since C++20)

c++中的allocator类

概述

  • 它用于将内存的分配和对象的构造分离开来. 它分配的内存是原始的、未构造的.+ Throws std::bad_alloc if allocation fails.+ 标准库中allocator类定义在头文件memory中
allocator<string> alloc;  // 定义了一个可以分配string的allocator对象
auto const p = alloc.allocate(n);  // 分配n个未初始化的string内存,即为n个空string分配了内存,分配的内存是原始的、未构造的

allocator用法

  • allocator a // 定义了一个名为a的allocator对象,它可以为类型T的对象分配内存+ a.allocate(n) // 分配能保存n个类型为T的对象的内存+ a.deallocate(p, n) // 释放T*指针p地址开始的内存,这块内存保存了n个类型为T的对象,p必须是一个先前由allocate返回的指针,且n必须是p创建时所要求的大小,且在调用该函数之前必须销毁在这片内存上创建的对象,这是因为在创建的过程中我们分配的是最原始的内存,所以在释放内存的时候也只能严格释放这片最原始的内存+ a.construct(p, args) // p必须是一个类型为T的指针,指向一片原始内存,arg将被传递给类型为T的构造函数,用来在p指向的原始内存上构建对象+ a.destory(p) // p为T类型的指针,用于对p指向的对象执行析构函数

详解

  • allocate用于分配原始内存

  • 正如前面说到,allocate出来的内存是最原始的,未构造的内存. 它的construct成员函数接受一个指针和零个或多个额外的参数,在给定位置构造对象, 额外的参数是用于初始化构造对象的

auto q = p;  // q指向最后构造的元素之后的位置
alloc.construct(q++);  // *q为空字符串
alloc.construct(q++, 10, 'c');  // *q为cccccccccc
alloc.construct(q++, "hi");  // *q为hi
  • 用完对象后,必须对这种构造的对象调用destory销毁,它接受一个指针,对指向的对象执行析构函数
while(q != p)
	alloc.destory(--q);

循环开始处,q是指向最后构造的元素之后的一个位置,调用destory之前我们先对q进行递减操作,所以第一次调用destory销毁的是最后一个元素,依次执行销毁操作直到q和p相等. 我们只能对真正构造了的元素进行destory操作,一旦元素被销毁,就可以重新使用这部分内存来保存其他string或归还给系统,释放内存通过调用deallocate完成

alloc.deallocate(p, n)

其中p不能为空,必须指向allocate分配的内存,而且大小参数n也必须与调用allocate分配内存时提供的大小参数相等。 + ### Return value
Pointer to the first element of an array of n objects of type T whose elements have not been constructed yet.  就是返回未构造的第一个元素

在STL中也会用allocate类

#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;
}

文章作者: AllenMirac
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 AllenMirac !
  目录