再学c++底漆(12)- c++中的高级内存管理

c++底漆的最后一章,虽说是高级主题,但其实是一些非常有用的东西,包括内存分配,RTTI,挥发性等等。

<强>

<强>新/删除

c++中内存方面最常用的就是新表达式和删除表达式。

实际上发生了三件事:

1)调用名为运营商的新标准库函数,分配足够大的原始的未类型化的内存,以保存指定类型的一个对象,

2)运行该类型的一个构造函数,用指定初始化式构造对象,

3)返回指向新分配并构造的对象的指针;


实际上发生了两件事:

1)对sp指向的对象运行适当的析构函数;

2)通过调用名为运营商删除的标准库函数释放该对象所占用的内存。


c++中还有一些更加“原子”的做法。

下面的两种方法来分配和释放未构造的原始内存

1)分配器类,能够针对某个类型进行内存分配,该类支持一个抽象接口,以分配内存并随后使用该内存保存对象,

2)标准库中的操作员新和删除,它们分配和释放需要大小的原始的,未类型化的内存;


下面的四种方法还提供不同的方法在原始内存中构造和撤销对象

1)分配器类定义名为构造和摧毁的成员,构造成员在未构造内存中初始化对象,摧毁成员在对象上运行适当的析构函数;

2)放置新表达式,接受指向未构造内存的指针,并在该空间初始化一个对象或是一个数组;

3)可以直接调用对象的析构函数来删除对象。运行析构函数并不释放对象所占有的内存;

4)使用uninitialized_fill, uninitialized_fill_n 和uninitialized_copy,进行构造或者拷贝构造。


<>强向量类的部分实现

向量。h

“代码”类template类向量{公众:向量():元素(0),first_free(0)(0){}结束无效push_back方法(const T&);//饺?静态std:: allocatoralloc;无效的重新分配();T *元素;T * first_free;T *结束;//瓆

私有成员的三个指针说明一下:

元素,指向数组第一个元素;

first_free,指向最后一个实际元素之后的元素;

,指向数组最后一个元素。

再学c++底漆(12)- c++中的高级内存管理”> <br/> </p> <p> <br/> </p> <p>矢量的大小等于first_free -元素;</p> <p>向量的容量等于结束-元素+ 1;</p> <p>剩余的自由空间是——first_free结束。</p> <p> <br/> </p> <p>还有两个函数,push_back方法用于向量中推动元素,重新分配用于重新分配内存。</p> <p> push_back函数的实现如下</p> <p> <pre code_snippet_id=“代码”类模板& lt; typename T>空白Vector
首先检查一下是否有剩余空间,如果没有空间的话调用重新分配函数重新分配内存,接下来在first_free所指向的内存块构建对象,最后将first_free指针向后移动一个单位。


高潮来了,重新分配函数!

先说明一下内存扩张策略:每次重新分配时分配两倍内存,函数首先计算当前在用的元素数目,将该数目翻倍,并请求分配器对象来获得所需数量的空间,如果向量为空,就分配两个元素。

这样的策略平摊下来的时间复杂度是O(1)。实现如下:

“代码”类模板& lt; typename T>空白Vector 
uninitialized_copy使用标准拷贝算法的特殊版本,这个版本在原始的未构造的内存中复制构造每一个元素;

的循环对旧数组中每个对象调用分配器的摧毁成员,逆序销毁元素,摧毁调用T的析构函数来释放对象的资源;

一旦复制并析构了元素,就释放原来占用的空间,不过在释放之前,斌需检查元素的合法性;

最后,并需重置指针以指向新分配并初始化的数组。


<强>重载新/删除

,,,,虽然c++标准库已经为我们提供了新的与删除操作符的标准实现,但是由于缺乏对具体对象的具体分析,系统默认提供的分配器在时间和空间两方面都存在着一些问题:分配器速度较慢,而且在分配小型对象时空间浪费比较严重,特别是在一些对效率或内存有较大限制的特殊应用中。比如说在嵌入式的系统中,由于内存限制,频繁地进行不定大小的内存动态分配很可能会引起严重问题,甚至出现堆破碎的风险;再比如在游戏设计中,效率绝对是一个必须要考虑的问题,而标准新与删除操作符的实现却存在着天生的效率缺陷。此时,我们可以求助于新与删除操作符的重载,它们给程序带来更灵活的内存分配控制。除了改善效率,重载新与删除还可能存在以下两点原因:

再学c++底漆(12)- c++中的高级内存管理