Slowing down your step,you will enjoy more.----wonderful
STL 的设计师对于内存的分配与回收可谓用尽浑身解数,无不怕哪一行语句影响了程序的效率。
一个经常使用容器的程序员或许都不知道内存配置器的存在。因为容器本身就隐藏了空间配置器的所有实现细节。
一般而言,C++ 中内存配置操作过程如下:
class Foo {...}
Foo *pf = new Foo;//配置内存,然后构造对象
delete pf; // 析构对象,然后释放内存
其中的 new 包含两部分的操作 (1) 调用::operator new 配置内存 (2) 调用Foo::Foo() 构造对象的内容
delete包含两部分操作 (1)调用Foo::~Foo() 将对象析构 (2)调用::operator:: delete 释放内存
然而STL 中将这两个操作区分开来,分别由不同的函数来完成
1,内存配置的头文件: stl_alloc.h
这里定义了一,二级 配置器,彼此合作,配置器名为alloc
2. 对象的构造和析构头文件: stl_construct.h
这里定义了全局函数construct() 和 destroy() 负责对象的析构和构造
由于内存配置比较麻烦,所以这里从 stl_construct.h 说起
stl_construct.h 中两个最基本的全局函数:construct() 和 destroy()
construct() :
construct()函数比较简单,仅仅是利用了placement new 操作符进行对象的构造,如下
template <class T1* p,const T2& value>
inline void construct(T1*p, const T2 &value){
new (p) T1(value);//placement new
}
不过这里要说明的是 placement new 操作符,这个操作符是把对象构造在一块已经分配好空间的地方,这里是p所指地方。然后placement new 操作符调用 T1::T1() 进行对象的构造。这样对象就被创建在用户指定的内存位置上了。
destroy()函数有一些复杂。它有两个版本
第一个版本:仅仅是调用对象的析构函数,进行对象的析构。如下
template <class T>
inline void destroy(T* pointer){//对象的指针
pointer->~T();
}
这个函数中可能让人迷惑的是 pointer->~T();这种写法 。出现这种原因可能是一直析构函数都是程序自动调用的。可能我们定义了自己的析构函数,但我们很少自己调用析构函数。 注意这里传进来的是要析构对象的指针。
第二个版本比较复杂:它会根据容器中实际的节点类型调用不同的析构函数。
出现这种现象也是必然的,因为容器中节点的类型可能很简单,如int ,double ,char 型 ,都很简单。不需要花费多少心思去进行析构。
但也可能很复杂,比如说节点是一个类的对象,并且这个对象中分配了大块内存,所以不得不一个一个节点的调用对象的析构函数进行析构。