【问题标题】:Why does the STL reserve an interface for Allocator?为什么 STL 为 Allocator 保留一个接口?
【发布时间】:2018-02-16 13:58:14
【问题描述】:

为什么 STL 为分配器保留一个接口? 以vector 为例:

template<class T,class Allocator = std::allocator<T>> 
class vector;

由于我们有很多选项可以分配内存和构造对象,例如
operator new,delete,new[],delete[],当我们创建对象时,它们几乎可以做我们需要的任何事情。
那么为什么像vector 这样的STL 容器需要一个分配器接口,如果我们不设置一个分配器接口,大多数时候它是默认的std::allocator为什么不直接使用 new 表达式?
如果目的是让用户自定义的分配行为成为可能,为什么不让用户提供自定义的operator new,new[]等呢?

【问题讨论】:

  • 如果你想改变vector分配内存的方式,如果没有分配器,你会怎么做?
  • 您不能为int 重载new,除非您重载了您可能不想做的全局变量。
  • 如果你想改变恰好一个向量,of many持有特定类型,分配它的内存,如果有,你会怎么做没有分配器?
  • @bigxiao C++ 被设计为尽可能通用(从没有堆的微控制器到具有分布式内存的超级计算机)。提供一个分配器就可以做到这一点。考虑到它是默认的,这真的没什么大不了的,所以如果你不想使用自定义分配器,你不需要做任何事情。分配器虽然比重载 new 运算符更灵活。
  • @Caleth 提供自定义operator new 怎么样,虽然不会改变内置类型

标签: c++


【解决方案1】:

如此具体的向量并改变它的分配方式而不改变所有向量的分配方式。

new 必须根据您分配的每个类型覆盖,或全局替换。 std::vector&lt;int&gt;std::vector&lt;int, some_other_allocator&gt; 可以使用不同的分配策略;事实上,分配器可以是有状态的并且有共享状态

一个经典的分配器是一种快速堆栈分配器,它在超出范围之前不会释放。

【讨论】:

  • 感谢您的回答。顺便说一下,我认为“overriden”这个词在这里可能不合适,也许“replaced”更好。见document of "replacement"
  • @bigxiao 覆盖和替换 new 是不同目的的不同事物。两者都适用于此。
【解决方案2】:

例如std::list&lt;T, Allocator&gt;也提供了这个接口。通常你会被告知不要使用链表,因为缓存位置不好。

如果您仍然需要使用链表,例如它永远不会使迭代器无效,您可以使用 pool allocator 优化 std::list

#include <boost/pool/pool_alloc.hpp>

template <typename T>
using pooled_list = std::list<T, boost::pool_allocator<T>>

这样您就可以优化您的代码,而无需重新实现std::list。这是policy based design 的示例。另一个例子是std::char_traits 代表std::basic_string

【讨论】:

    猜你喜欢
    • 2012-08-02
    • 2023-03-19
    • 2014-09-16
    • 2017-06-22
    • 2011-04-24
    • 2021-11-02
    • 1970-01-01
    • 2014-01-31
    • 1970-01-01
    相关资源
    最近更新 更多