前言
在上节中我们主要分析了chunk_alloc
函数,在本小节中,我们先对第一级配置器和第二级配置器的使用做个整理,随后再介绍空间配置器提供的初始化未初始化空间的接口。
默认使用的配置器
当我们使用vector
这些容器时,其实是默认指定了使用的空间配置器的,比如vector
在源码中的模板头是这样的template <class T, class Alloc = alloc>
,默认指定了配置器为alloc
。
而alloc
则代表具体的哪一个配置器。
在SGISTL源码中是这样指定alloc
的,它是一个typedef。
# ifdef __USE_MALLOC
typedef malloc_alloc alloc;
...
#else
...
typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
如果宏定义了__USE_MALLOC
,则使用第一级配置器,如果没有,则使用第二级配置器。
而__USE_MALLOC
的定义又涉及到了其他宏,最终由gcc的版本而定,我不知道当时gcc的版本是多少,就不太明白__USE_MALLOC
到底定义没有,因为它是一个条件编译。而在《STL源码剖析》书上说的__USE_MALLOC
没有定义,那应该当时SGISTL默认使用的就是第二级配置器。
不论使用的哪一种,SGISTL都统一了配置器的接口,代码如下
template<class T, class Alloc>
class simple_alloc {
public:
static T *allocate(size_t n)
{ return 0 == n? 0 : (T*) Alloc::allocate(n * sizeof (T)); }
static T *allocate(void)
{ return (T*) Alloc::allocate(sizeof (T)); }
static void deallocate(T *p, size_t n)
{ if (0 != n) Alloc::deallocate(p, n * sizeof (T)); }
static void deallocate(T *p)
{ Alloc::deallocate(p, sizeof (T)); }
};
可以看到申请/释放空间都统一调用的是Alloc
的接口,而Alloc
默认指定是alloc
,alloc
对应的是第一级配置器/第二级配置器。
你可能还会有疑问,即那么simple_alloc
在哪里进行实例化呢,毕竟没有实例化的话,那些容器根本就用不了空间配置器提供的外部接口。
答案是就在容器内部进行,如vector
中的typedef simple_alloc<value_type, Alloc> data_allocator
,指定了分配的单位以及使用的配置器,在vector
内部中分配及释放内存都使用simple_alloc
提供的接口。
理解以上所述十分关键,因为这涉及到空间配置器与其他STL组件之间的联系。总的来说,就是空间配置器里面分第一级配置器和第二级配置器,不论是用哪一个,都封装了一套标准的接口(simple_alloc
)供其他STL组件使用,而其他组件在内部定义属于自己的空间配置器(即指定分配的单位等)
小结
在本小节中,我们从宏观的角度来观察了空间配置器和其他STL组件的一些联系,这对我们把握STL整体很有帮助。空间配置器中还有一些函数没有进行分析,如uninitalized_copy
等函数,由于它们涉及到迭代器的类别等方面的知识,还是放在讲完了迭代器再分析。