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

时间:2019-02-01 16:08:14

标签: c++ c++11 stl containers

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

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

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

我只打算用一张查找地图来创建类似的东西

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

我的理由是,我可以通过erase[id] = new 'overwrite!'操作将其删除,而不必担心。 但是然后我该如何添加相同的Node实例来说另一张地图

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

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

1 个答案:

答案 0 :(得分:4)

使用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