const malloc_allocator<t>&) {
return false;
}
你会期望一个allocator,它的不同对象是不可替换的吗?当然--但很难提供一个简单而有用的例子。一种明显的可能性是内存池。它对大型的c程序很常见,从几个不同的位置(“池”)分配内存,而不是什么东西都直接使用malloc()。这样做有几个好处,其一是it only takes a single function call to reclaim all of the memory associated with a particular phase of the program。 使用内存池的程序可能定义诸如mempool_alloc和mempool_free这样的工具函数,mempol_alloc(n, p)从池p中分配n个字节。很容易写出一个mmepool_alocator以匹配这样的架构:每个mempool_allocator对象有一个成员变量以指明它绑定在哪个池上,而mempool_allocator::allocate()将调用mempool_alloc()从相应的池中获取内存。[注1]
最后,我们到了allocator的定义体中一个微妙的部份:在不同的类型之间映射。问题是,一个allocator类,比如malloc_allocator<int>,全部是围绕着单个value_type构建的:malloc_allocator<int>::pointer是int*,malloc_allocator<int>().allocate(1)返回足够容纳一个int对象的内存,等等。然而,通常,容器类使用malloc_allocator可能必须处理超过一个类型。比如,一个list类,不分配int对象;实际上,它分配list node对象。(我们将在下一段落研究细节。)于是,当你创建一个std::list<int, malloc_allocator<int> >时,list必须将malloc_allocator<int>转变成为处理list_node类型的malloc_allocator。
这个机制称为重绑定,它有二个部份。首先,对于给定的一个value_type是x1的allocator类型a1,你必须能够写出一个allocator类型a2,它与a1完全相同,除了value_type是x2。其次,对于给定的a1类型的对象a1,你必须能够创建一个等价的a2类型对象a2。这两部分都使用了成员模板,这也就是allocator不能被老的编译器支持,或支持得很差的原因。
template <class t> class malloc_allocator
{
public:
template <class u>
malloc_allocator(const malloc_allocator<u>&) {}
template <class u>
struct rebind { typedef malloc_allocator<u> other; };
...
};
这其实意味着一个allocator类不能仅仅是单个类;它必须是一族相关类,每个都有它自己的value_type。一个allocator类必须要有一个rebind成员,因为它使得从一个类变成同族的另外一个类成为可能。