本文作者:campos 本文出处:http://www.mykernelspace.com (转载请保留此行,谢谢)
最后我们来看看这个被容器类广泛include的bits/allocator.h文件。
这个文件定义了allocator这个模板类。回想一下上次在new_allocator中看到的:这个类主要定义了几个模板类型的别名,还有重要的函数(allocate, deallocate, construct, destruct)。实际上,这个类没有任何的数据成员,纯粹是一个utility类。现在要分析的类allocator就是从这个类继承来的。下面是代码:
template<typename _Tp>
class allocator: public ___glibcxx_base_allocator<_Tp>
{
//一些类型别名的定义,与new_allocator里的定义一致
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef _Tp* pointer;
typedef const _Tp* const_pointer;
typedef _Tp& reference;
typedef const _Tp& const_reference;
typedef _Tp value_type;
//功能未知的部分。定义了另一个类型的模板结构,唯一的成员就是另外一个类型allocator的typedef。
template<typename _Tp1>
struct rebind
{ typedef allocator<_Tp1> other; };
//默认构造函数
allocator() throw() { }
//拷贝构造函数,调用父类的构造函数
allocator(const allocator& a) throw()
: ___glibcxx_base_allocator<_Tp>(a) { }
//参数为另外一个类型allocator的拷贝构造函数
template<typename _Tp1>
allocator(const allocator<_Tp1>&) throw() { }
//析构函数
~allocator() throw() { }
//继承其他所有的定义
};
同时在这个类的声明的后面,也同样将==和!=两个操作符定义为永远相等。
//==操作符永真
template<typename _T1, typename _T2>
inline bool
operator==(const allocator<_T1>&, const allocator<_T2>&)
{ return true; }
//!=操作符永假
template<typename _T1, typename _T2>
inline bool
operator!=(const allocator<_T1>&, const allocator<_T2>&)
{ return false; }
在这个allocator的真正声明前面有一个specialization定义:
//前向定义
template<typename _Tp>
class allocator;
//对于void类型做特殊处理
template<>
class allocator<void>
{
//定义几个别名,pointer类型为void*。最重要的区别就是去掉了reference类型,因为void&是没有意义的。当然这个void的value_type我也得想想是什么意思:)
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;
//同样神秘的rebind,应该会在以后知道它的用途。这里我被迫卖个关子。
template<typename _Tp1>
struct rebind
{ typedef allocator<_Tp1> other; };
};
好了,其实allocator也挺简单的,至少现在看来是这样。整个这个allocator最重要的allocate和deallocate只是调用了全局的operator new和operator delete。construct和destruct函数调用了全局的new expression和对象的析构函数。根据现在所看到的代码,可以想象的allocator在容器中的用法就是:声明一个allocator对象作为容器的成员,然后任何内存分配的任务都由这个allocator对象来实现。其实经常看到的一个容器声明就是(一般出现在错误中),template<typename _Tp, typename _Alloc = allocator<_Tp> > 。我还没有自己写过自己的allocator,所以一般都用的是系统默认的allocator。
到现在,分析过的代码有auto_ptr,iterator和allocator。接下来就可以正式看看这些基本的STL元素是如何使用的。下次就打算挑一个non-associative的容器来看看,其他的non-associative的容器依此类推。然后再下次就找个associative的容器来研究研究,尽量达到举一反三的作用。