CUJ:标准库:Allocator能做什么?[15]

[入库:2005年8月18日] [更新:2007年3月24日]

本文简介:选择自 taodm 的 blog

展望未来

    如果你想写一个如同malloc_allocator这样简单的allocator,应该没有困难。(前提是你正在使用一个比较现代的编译器)。然而,如果你的心比较大,--基于内存池的或支持非标指针类型的allocator--情况就比较不令人满意了。

    如果你想使用可能的类指针(pointer-like)类型,它必须支持哪些操作?它必须有一个null值吗?如果是的话,那个值应该如何书写?你能使用类型转换吗?你如何在类指针对象与普通指针间进行转换?你必须要考虑操作指针时抛的异常吗?我在这最后一节提出了一些假设;c++标准没有指明这些假设的对错。这些细节都留给了具体的标准库的实现,即使某个实现完全忽略可选指针类型也是合法的。c++标准还遗留了一些没有答案的问题,比如当一个allocator的不同实例不可互换时,将发生什么。

    幸运的是,情形并不象标准(§ 20.1.5,第4-5段)中的词汇所描述得那么可怕。标准留下没有答案的问题,是因为在制订标准时,c++标准化委员会对答案达不成共识;对allocator的必要的经验还不存在。每个参与制订的人都认为这是一个临时的补丁,其中的含糊肯定将在将来的修订中被去除。

    等一下,如果你关心可移植性,最好还是远离可选的指针类型,而,如果你乐意接受一些限制,就能安全地使用诸如mempool_allocator这样不同对象实体间差别很大的allocator。所有主流标准库的实现现在都在某个方面不支持这样的allocator,而且不同实现间的差别不大。

    正如容器接受一个allocator作为模板参数,容器的构造函数也接受一个allocator作为参数。容器保留这个参数的一份拷贝,并使用这个拷贝来处理所有的内存管理;容器的allocator一旦在构造函数中初始化完成,就终生不变。

    唯一的问题是当你运行一个需要两个容器在内存管理上进行协同的操作时,会发生什么。在标准库中确实存在两个这样的操作:swap()(所有容器)和std::list::splice()。原理上,可以以这样几个不同的方式处理他们:

l         禁止在两个allocator不等价的容器间进行swap()和splice()。

l         swap()和splice()中放入一个allocator等价性的测试。如果不等价,降格调用copy()和赋值运算。

l         只提供swap():如同对容器中的数据一样,交换它们的allocator。(很难找出如何将它推广到splice上.它同样也带来一个问题:如何swap没有定义赋值运算符的东西?)

    如果你能避免对可能具有不同allocator的容器使用swap()和splice(),一切都很安全。在实践中,我没有发现这会造成严重束缚:你需要严格练习安全使用诸如内存池这类特性,而你或许并不想不加选择地混用使用不同allocator的容器。

    部分因为不熟悉,部分因为c++标准的要求并不令人满意,目前对allocator的绝大多数的使用都很简单。由于c++社群对allocator变得越来越熟悉,并且标准已被阐明,我们能期待更复杂的使用将会浮现。

listing 1: a sample allocator based on malloc

template <class t> class malloc_allocator

{

public:

  typedef t                 value_type;

  typedef value_type*       pointer;

本文关键:CUJ、allocator、STL、Matt Austern
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top