当分配一大块内存时,我们通过计划在这块内存上按需求构造对象。在此情况下,我们希望将内存分配和对象构造分离。这意味着我们可以分配大块内存,但是真正需要时才真正执行对象创建操作。
标准库allocator类定义在头文件memory中,它将内存分配和对象构造分开
allocator<string> alloc; //可以分配string的allocator对象
auto const p = alloc.allocate(n); //分配n个未初始化的string
标准库allocator类以及算法
allocator<T> a //定义了一个名为a的allocator对象,它可以为类型为T的对象分配内存
a.allocate(n) //分配一段原始的、未构造的内存,保存n个类型为T的对象
a.deallocate(p, n) //释放从T*指针p中地址开始的内存,这块内存保存了n个类型为T的对象,调用deallocate前,用户必须对每个在这块内存中创建的对象调用destroy
a.construct(p, args) //args被传递给类型为T的构造函数,用来在p指向的内存中构造一个对象
a.destory(p) //p为T*类型的指针,此算法对p指向的对象执行析构函数
allocator分配未构造的内存
allocator分配的内存是未构造的(unconstructed),我们按需要在此内存中构造对象。
auto q = p; //q指向最后构造的元素之后的位置
alloc.construct(q++); // *q为空字符串
alloc.construct(q++, "hi"); //*q为hi
为了使用allocate返回的内存,我们必须使用construct构造对象。使用未构造的内存,其行为是未定义的
当我们用完对象后,必须对每个构造的元素调用destory来销毁它们。函数destory接受一个指针,对指向的对象执行析构函数
while (q != p){
alloc.destory(--q); //释放我们真正构造的string
}
在循环开始处,q指向最后构造的元素之后的位置,最后一步循环中我们destory了第一个构造的元素,随后q将与p相等,循环结束。
一旦元素被销毁后,可以使用这部分内存来保存其他string,也可以将其归还给系统
alloc.deallocate(p, n);
我们传递给deallocate的指针不能为空,它必须指向由allocate分配的内存。而且,传递给deallocate的大小参数必须与调用allocate分配内存时提供的大小参数具有一样的值
拷贝和填充未初始化内存的算法
标准库还为allocator类定义了两个伴随算法,可以在未初始化内存中创建对象,定义在memory头文件中。
allocator算法
uninitialized_copy(b, e, b2) //从迭代器b和e指出的输入范围中拷贝元素到迭代器b2指定的未构造的原始内存中
uninitialized_copy_n(b, n, b2) //从迭代器b指向的元素开始,拷贝n个元素到b2开始的内存中
uninitialized_fill(b, e, t) //在迭代器b和e指定的原始内存范围中创建对象,对象的值均为t的拷贝
uninitialized_fill_n(b, n, t) //从迭代器b指向的内存地址开始创建n个对象
//分配比vi中元素所占空间大一倍的动态内存
auto p = alloc.allocate(vi.size()*2);
//通过拷贝vi中的元素来构造从p开始的元素
auto q = uninitialized_copy(vi.begin(), vi.end(), p);
//将剩余元素初始化为42
uninitialized_fill_n(q, vi.size(), 42);
一次uninitialized_copy调用会返回一个指针,指向最后一个构造的元素之后的位置
#include <iostream>
#include <string>
#include <memory>
using namespace std;
int main() {
allocator<string> alloc;
auto const p = alloc.allocate(100); //分配100个未初始化的string
string s;
string* q = p; //q指向第一个string
while (cin >> s && q != p + 100)
alloc.construct(q++, s); //用s初始化*q
const size_t size = q - p; //记住读取了多少个string
for (size_t i = 0; i < size; i++) {
cout << p[i] << " " << endl;
}
while (q != p) //使用完毕后释放已构造的string
alloc.destroy(--q);
alloc.deallocate(p, 100); //释放内存
return 0;
}