如何在自定义容器中正确使用std :: allocator?

时间:2019-07-15 21:24:05

标签: c++ memory-management allocator

我正在尝试开发自己的容器,该容器将实现哈希表。主要要求是此容器必须与STL兼容。现在,我无法了解如何为内部容器需求分配内存和初始化对象。

主要问题是如何管理此类容器的密钥?我是否需要为哈希函数从键生成的索引分配另一个存储空间?然后通过节点存储桶将它们链接到实际存储?

我的容器有模板参数。

template<
    class Key, class T, class Hasher = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Alloc = std::allocator<std::pair<const Key, T>>>
class my_hashtable_v1 {

但是随后我使用这样的内部成员类型为我的容器分配节点。

template<class T>
struct ch_node_t : hash_node {
    template<class... Args>
    ch_node_t(Args&&... args) : value(std::forward<Args>(args)...) {
    }
    T value;
};

using node_type = ch_node_t<T>;
using storage_allocator_ = typename Alloc::template rebind<node_type>::other;

以这种方式分配节点是否正确?这是来自insert方法的代码。

auto node = &storage_[slot];
if(!node_traits::is_allocated(*node)) {
  new(node) node_type(v.second);
  node_traits::link_head(*node);
  --freelist_;
}

storage是指向已分配池的指针。这就是我分配池的方式:

storage_ = storage_allocator_.allocate(size_);

我无法理解的主要事情是如何正确使用std::allocator<std::pair<const Key, T>>管理节点密钥?我需要分别创建诸如索引和存储之类的东西吗?

探索std::unordered_map代码很难获得这些答案,这就是为什么我要求您在开发自定义容器中提供指导。

1 个答案:

答案 0 :(得分:1)

为了分配除Node(称为std::allocator_traits<Alloc>::value_type)以外的另一种类型的对象(我们称为T),其中Alloc是可能的自定义分配器类型,您必须rebind分配器才能获得类型Node的分配器:

using node_alloc_t = std::allocator_traits<Alloc>::rebind_alloc<Node>;
node_alloc_t node_alloc;
node_alloc.allocate(size_);
  

但是如何正确处理密钥?我需要为索引创建另一个存储吗?

您不一定需要为密钥创建单独的存储。您可以将它们存储在节点中。例如,这就是基于树的容器的工作方式。

  

我的节点类型不包含任何键。

如果要单独存储密钥,则确实需要为其分配存储空间。