基于C++11的allocator类的分析

引入原因

当我们想要在堆空间中开辟一个对象时,我们常常使用new操作符将内存分配和对象构造一口气完成了。这从一方面来看是方便了,但也减少了一些灵活度。delete操作符也是相似的将对象析构和释放内存绑定在一起。

看以下代码:

const string* p=new string[n];
string s;
string *q=p;
while(cin>>s&&q!=p+n)*q++=s;
delete [] p;

我们发现要用到的对象初始化了一次,后面又赋值了一次。没用到的对象初始化了一次。这些没有必要的初始化会极大的影响性能。并且没有默认构造函数的类就不能够构造动态数组了。

allocator类的引入

allocator的基本操作:

allocator<T> a//定义了一个allocator对象可以为类型T的对象分配内存 
a.allocate(n) //分配一段原始的,未构造的内存。能够保存n个T类型的对象,将这个构造后的首地址返回
a.deallocate(p,n)//释放从p到p+n区域的内存,大小为n个T对象。注:1.释放前必须析构对象2.必须是由allocator创建的空间
a.construct(p,args)//p必须是一个T*类型的指针,args被传给T的构造函数,用来在p中指向的内存构造一个对象
a.destory(p)//p为T*类型的指针,对p指向的对象调用析构函数

标准库的allocator类定义于头文件<memory>中,它帮助我们将内存分配和对象构造分离开来。类似vector,allocator是一个类模板,必须要提前给与其参数类型(不然不知道要分配多少字节的内存)。

几个简单的例子

allocator<string>alloc;
const auto p=alloc.allocator(n);   //分配n*sizeof(string)大小的原始内存给p对象

auto q=p;
alloc.construct(q++);
alloc.construct(q++,10,'c');
alloc.construct(q++,"hi");   //只能逐位的进行构造

cout<<*p<<endl;
cout<<*q<<endl;   //ERROR:使用未构造的内存行为是未定义的

while(q!=p)alloc.destory(--q);  //从前面构造过来,再从后面析构回去

alloc.deallocate(p,n); //释放内存操作    

为allocator所设计的伴随算法

uninitialized_copy(b,e,b2)//将b和e区间的元素拷贝到b2为起点的原始内存中。注:b2指向的内存必须足够容下b到e区间的元素
uninitialized_copy_n(b,n,b2)//将b到b+n区间的元素拷贝到b2为起点的原始内存中。注:b2指向的内存必须足够容下b到e区间的元素
uninitialized_fill(b,e,t)//在迭代器b和e指定的原始内存范围中创建对象,对象的值均为t的拷贝
uninitialized_fill_n(b,n,t)在迭代器b和b+n指定的原始内存范围中创建对象,对象的值均为t的拷贝。注:区间必须可以容下这么大小的元素

一个关于vector重新分配内存的模拟:

auto p=alloc.allocate(vi.size()*);
auto q=uninitialized_copy(vi.begin(),vi.end(),p);//返回一个copy后最后一个元素之后的地址
uninitialized_fill_n(q,vi.size(),42);

一些额外的内容

其实C++中还存在operator new(operator new[])来构建原始空间,以及operator delete(operator delete [])来释放空间。我们可以通过自定义自己的版本来对空间的分配加强控制。

在allocator类出现前,是通过定位new和显示的调用析构函数来实现构造对象和析构对象。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Reol520

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值