【问题标题】:How to allocate std::map's internal RB_tree node in memory pool in C++11?如何在 C++11 的内存池中分配 std::map 的内部 RB_tree 节点?
【发布时间】:2019-10-17 21:20:53
【问题描述】:

std::map 定义复制如下:

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >
> class map;

基于std::map的定义,我们可以为其KeyValue提供定制的分配器。

问题:

  1. 在大多数情况下,std::map 是由 RB 树实现的。我们如何为 RB 树节点提供定制的分配器?恐怕我们做不到。
  2. 如果第一个问题的答案是我们可以为RB树节点提供自定义分配器,我们可以为其他基于节点的容器提供自定义分配器(例如,std::list 和 std::set)。请确认我的理解是否正确。

【问题讨论】:

  • 我不确定我是否正确理解了您的问题,但如果您提供自定义分配器,所有节点都将使用提供的分配器进行分配。
  • 感谢您的帮助。我需要知道节点大小来计算内存池大小。他们使用相同的分配器,但它分配的内存大小为 _Rb_tree_node 而不是 std::pair.
  • 地图节点的大小取决于 STL 的实现。如果我没记错的话,在我的系统上,它是对的大小加上 3 * sizeof(std::size_t) 来自节点指针。也许以下链接有帮助:stackoverflow.com/questions/22951378/…
  • 谢谢,使用 _Rb_tree_node 而不是对的大小加上 3 * sizeof(std::size_t) 更安全

标签: c++ c++11 stdmap allocator


【解决方案1】:

IIRC,您作为map 模板参数提供的分配器类型也用于分配节点(即其allocate 成员函数)。例如,您可以在source code of libstdc++ 中观察到这一点:

typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
   rebind<value_type>::other _Pair_alloc_type;

typedef _Rb_tree<key_type, value_type, _Select1st<value_type>,
    key_compare, _Pair_alloc_type> _Rep_type;

std::map 的原始分配器参数 _Alloc重新绑定到映射的值类型,并作为模板参数传递给 _Rb_tree。在那里,分配器又是rebound to the node type _Rb_tree_node&lt;_Val&gt;

typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
   rebind<_Rb_tree_node<_Val> >::other _Node_allocator;

这种机制的典型用法是利用一些基于内存池的分配器,这可能会大大加快节点分配速度。但是,请注意,这种技术通常并不简单。例如,对于std::unordered_map,(回弹)分配器类型用于节点分配和桶数组分配。在allocate 成员函数中,需要区分两种分配类型并使用内存池仅用于节点分配。

std::map 没有桶数组,所以理论上分配器应该只用于节点的分配。但是,我不确定标准是否保证了这一点。

【讨论】:

  • 感谢您的帮助,我试过了,它有效,我需要知道std::map节点的大小来预先计算轮询内存大小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-14
  • 1970-01-01
  • 1970-01-01
  • 2017-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多