C++ allocator类
将内存分配和对象构造组合在一起引起的浪费
在使用动态数组,new操作是将分配内存和构建对象组合在一起,delete操作是把对象析构和内存释放组合在一起。但是在分配一大块内存时,希望能够将内存分配和对象构造分离起来,避免构建一些用不到的对象。
将内存分配和对象构造组合在一起引起的浪费
string *const p = new string[n];
stirng s;
string *q = p;
while(cin >> s && q!=p+n)
*q++ = s;
const size_t = size = q-p; //计算读取了多少个string
delete[] p;
new分配并初始化了n个string,但是我们可能不需要n个string。这样我们就创建了一些永远都用不到的对象。对于确实要用到的对象,我们赋值了两次,一次是初始化,随后是赋值时。
更重要的是,那些没有构造函数的类就不能使用动态数组了。
allocator类
allocator类定义在文件memory中,它帮助我们把内存分配和构建对象分离开来。
它分配的内存是未构造的,原始的。
allocator<string> alloc;
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的对象,p必须是调用allocate返回的指针 |
a.construct(p, args) | args被传递给类型为T的构造函数,用来在p指向的内存构造一个对象 |
a.destory(p) | p为T*类型的指针,实现对p指向的对象指向析构函数 |
allocator分配未构造的内存
allocator分配的是未构造的内存,所以我们需要在此内存中构造对象。consturct成员函数接受一个指针和零个或多个额外参数。
auto q = p; //q指向最后构造的元素之后的位置
alloc.construct(q++); //*q为空字符串
alloc.construct(q++, 10, 'c'); // *q为cccccccccc
alloc.construct(q++, "hi"); //*q为hi
不要在未构建对象使用
cout << *p << endl; //正确,使用string的输出运算符
cout << *q << endl; //错误,q指向的是未构建的内存
销毁对象
当我们使用完对象后,必须对每个构造的元素调用destory来销毁它们,随后再使用deallocate去释放内存。
while(q != p){
alloc.destory(--q);
}
//当销毁对象之后,去进行内存的释放
alloc.deallocate(p, n);
拷贝和填充未初始化内存的对象
allocator算法 | 功能 |
---|---|
unintialized_copy(b, e, b2) | 从迭代器b和e指出的输入范围中拷贝元素到迭代器b2指定的未构造的原始内存。b2指向的内存必须足够大,能容纳输入序列中元素的拷贝 |
unintialized_copy_n(b, n, b2) | 从迭代器b指向的元素开始,拷贝n个元素到b2指定的未构造的原始内存。 |
unintialized_fill(b, e, t) | 从b和e指定的原始内存范围中创建对象,对象的值为t的拷贝 |
unintialized_fill_n(b, n, t) | 从迭代器b指向的内存地址开始创建n个对象,值为t。 |