关闭

C++内存分配与对象构造的分离

发表于:2015-4-13 09:50

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:青藜学士    来源:51Testing软件测试网采编

  在C++中,我们基本用new(delete)操作符分配(释放)内存。new操作符为特定类型分配内存,并在新分配的内存中构造该类型的一个对象。new表达式自动运行合适的构造函数来初始化每个动态分配的类类型对象。即new表达式既分配了内存同时也构造了对象。
  然而,我们一定会遇到这样的情况:预先分配用于创建新对象的内存,需要时在预先分配的内存中构造每个对象。即将内存分配与对象构造分开进行,这样做的理由是:
  (1)在内存分配时构造对象很浪费,可能会创建从不使用的对象。
  (2)当实际使用预先分配的对象时,被使用的对象很可能要重赋新值。
  string* pstr = new string[5];
  上面举了个不合适的例子(当然你应该用vector<string>来代替),毫无疑问被分配的5个string空间是被string默认构造函数初始化了,而且接下来你肯定得对pstr[0...4]重新赋值。所以new操作符这种分配特点会增加运行时开销。尤其是某些用户的类类型要求对象分配更快一些,做法通常是:预先分配用于创建新对象的内存,需要时在预先分配的内存中构造每个新对象。
  一、分配原始内存
  C++提供两种方法分配和释放未构造的原始内存:
  (1)allocator类,它提供可感知类型的内存分配。这个类支持抽象接口,以分配内存并随后使用该内存保存对象。
  (2)标准库中的operator new和operator delete,它们分配和释放需要大小的原始的,未类型化的内存。
  1、allocator类
  allocator类是一个模板,它提供类型化的内存分配以及对象构造与撤销。它支持的操作如下:
  allocator类将内存分配和对象构造分开。当allocator对象分配内存的时,它分配适当大小并排列成保存给定类型对象的空间。它分配的内存是未被构造的,allocator的用户必须分别construct和destroy放置在该内存中的对象。
  vector的自增长告诉我们:vector为了实现快速内存分配,其实际分配的空间要比当前需要的空间多一些。(实际空间因库的实现不同而不同),下面为了说明allocator的使用,我们简陋地实现STL vector中的push_back操作。
template <class T> class VECTOR
{
public:
VECTOR() : elements(NULL), first_free(NULL), end(NULL){}
void push_back(const T&);
private:
static allocator<T> alloc;
void reallocate();
T *elements;
T *first_free;
T *end;
};
  elements:指向数组的第一个元素;first_free:指向最后一个实际元素之后的那个元素;end:指向数组本身之后的那个元素。看下面这张图可能更清楚一点。
template <class T> void VECTOR<T>::push_back(const T& t)
{
if (first_free == end)                    //确认是否有可用空间
{
reallocate();                        //分配新空间并复制现存元素
}
alloc.construct(first_free, t);            //构造新元素
++first_free;
}
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号