new的缺陷
一般情况下使用new分配的空间会造成空间的浪费,因为new分配的空间将内存分配和对象构造组合在一起,造成不必要的浪费。
string *p=new string[1024];
string s;
string *q=p;
while(cin>>s&&q!=p+n)
*q++=s;
const size_t size=q-p;
delete[] p;
上述的案例我们用new分配到了1024个string,但是实际我们可能根本用不到1024那么大的空间,那么剩下的空间就会浪费,因此C++中引入了allocator类俩来进行内存的分配。
allocator类
标准库中将allocator类定义在头文件memory中,它可以实现内存分配和对象指定的分离,allocator使用模板定义实现的,因此使用时需要指定数据类型。关于allocator的相关操作如下表:
allocator<string> alloc;
auto const p=alloc.allocate(100);
auto q = p;//q指向最后构造的元素之后的位置,q指向的位置是未构造的
alloc.construct(q++);//*q为空字符串
alloc.construct(q++,10,'c');//*q为cccccccccc
alloc.construct(q++,"hi");//*q为hi
std::cout << *p << std::endl; // 正确:使用string的输出运算符
//std::cout << *q << std::endl; // 灾难:q指向未构造的内存
cout << p[0] << endl;//访问分配的元素
cout << p[1] << endl;
cout << p[2] << endl;
while (q != p)
{
cout << q - p << endl;//q是下一个未构造的位置
alloc.destroy(--q);
}
alloc.deallocate(p, 100);//将分配的内存释放
为了使用allocate返回的内存,我们必须用construct构造对象。使用未构造的内存,其行为是未定义的。
allocator类伴随算法
allocator中定义了两类伴随算法,可以在未初始化的内存中创建对象。
vector<int>vi{1,5,7,8,9,6,1,2};
allocator<int> alloc;
//分配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);
for (int i=0;i<vi.size()*2;i++)
{
cout << p[i] << endl;
}
alloc.deallocate(p, vi.size() * 2);
uninitialized_copy函数是返回的是构造元素之后的指针。