目录
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出来的内存是最原始的,未构造的内存. 它的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;
}