创建和管理查找容器的正确方法

Correct way to create and manage look up containers

本文关键字:方法 管理 查找 创建      更新时间:2023-10-16

实例创建查找映射的正确方法。我有一个定义节点的结构如下

struct Node
{
    int32_t id;
    std::string name;
    ...
}

我想创建 2 个查找地图,基于 ID 和另一个基于名称。节点中还有其他属性也需要查找映射,但这些属性是动态的,因此并非每个 Node 实例都会在这些附加映射中具有查找条目。

只需一张查找地图,我计划创建类似的东西

typedef std::unoredered_map<int32_t, std::unique_ptr <Node> > NodesById;

的理由只是我可以通过erase[id] = new 'overwrite!'操作将其删除,而不必担心。但是我怎样才能添加相同的节点实例来表示另一个映射

typedef std::unoredered_map<std::string, std::unique_ptr <Node> > NodesByName;

我无法将相同的节点实例放入unique_ptr。所以我的问题是将 Node 实例存储到多个查找表中并仍然实现智能内存管理的正确方法是什么。

使用 boost::multi_index

#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <string>    
#include <cassert>    
struct Node {
    int32_t id;
    std::string name;
    Node(int32_t id, std::string name)
        : id(id)
        , name(move(name))
    {}
    // Just to demonstrate that Node doesn't need to be copyable/moveable.
    Node(Node const&) = delete;
    Node& operator=(Node const&) = delete;
};
namespace mi = boost::multi_index;
using NodeSet = mi::multi_index_container<
      Node
    , mi::indexed_by<
            mi::hashed_unique<mi::member<Node, int32_t, &Node::id>>
          , mi::hashed_unique<mi::member<Node, std::string, &Node::name>>
      >
    >;
int main() {
    NodeSet s;
    s.emplace(1, "Alice");
    s.emplace(2, "Bob");
    assert(s.find(1)->name == "Alice");
    assert(mi::get<0>(s).find(1)->name == "Alice"); // Same as above.
    assert(mi::get<1>(s).find("Alice")->id == 1);
}

按值存储比在其中存储unique_ptr更有效。由于NodeSet不需要Node可复制或可移动,因此没有必要在此处使用unique_ptr