【问题标题】:Pointer/Reference to element in std::unordered_set指向 std::unordered_set 中元素的指针/引用
【发布时间】:2016-02-03 20:57:06
【问题描述】:

我使用std::unordered_set 来存储我的数据对象。 但是现在我想为它们创建一个指针/引用,例如(没有散列函数...):

struct Node
{
  Node* parent;
  ...
};
std::unordered_set<Node> list;

是否可以使用 std::unordered_set&lt;Node&gt;::const_iterator ? 如果(不删除元素!)迭代器“排序”发生变化,我不确定如何找出这些信息?

更新更多细节以便更好地理解:

我选择 std::unordered_set 是因为查找时间固定。 为了提高我的 C++ 技能,最好知道要改变什么。

#include <iostream>
#include <string>
#include <stdint.h>
#include <vector>

#include <unordered_set>


struct Link;
struct Node
{
    uint32_t id;
    std::unordered_set<Link> link;

    Node(uint32_t id) : id(id)
    {
    };

    bool operator==(Node const& rhs)
    {
        return id == rhs.id;
    }
};

struct Link
{
    Node* parent;
    uint32_t param1; // ..... and more

    bool operator==(Link const& rhs)
    {
        return parent == parent.rhs && param1 == rhs.param1;
    }
}


namespace std
{
    template<> struct hash<Node>
    {
        size_t operator()(Node const& node) const
        {
            return hash<uint32_t>()(node.id);
        }
    };

    template<> struct hash<Link>
    {
        size_t operator()(Link const& link) const
        {
            return  hash<uint32_t>()(link.param1) ^ hash<Node>()(*link.parent);
        }
    };    
}

int main()
{
    std::unordered_set<Node> nodes;
    nodes.emplace( Node(1) );
    nodes.emplace( Node(2) );
    nodes.emplace( Node(3) );    
}

【问题讨论】:

  • 顺序对您有什么影响?
  • 如果您使用的是无序集,您是否已经决定不关心迭代器通过数据的顺序?您是否尝试过使用const_iterator?发生了什么?什么有效?什么没有?
  • unordered_set 的用法似乎很奇怪。您使用整个 Node 作为自己的密钥的动机是什么?

标签: c++ c++11 unordered-set


【解决方案1】:

您可以在unordered_set 内拥有指向Node 对象的指针。但是这些指针必须是Node const*(即const)。

即使对unordered_set 进行了插入,指针也不会失效。例如,您可以将这些指针存储在另一个 unordered_set&lt;Node const*&gt; 中:

std::unordered_set<Node, hasher> s{{1}, {2}, {3}};
std::unordered_set<Node const*> s_ptr;

for(auto &&i : s) {
  s_ptr.insert(&i);
}

Live Demo

【讨论】:

    【解决方案2】:

    在插入期间发生重新散列时,无序容器中的迭代器会失效。我不会试图预测或避免重新散列。只要您不插入新项目,迭代器就保持有效。您可以删除现有项目。

    请注意,即使发生重新散列,值也不会移动。在您删除该特定项目之前,指针和引用不会失效。这意味着您可以执行Node* parent 或类似的操作。

    不清楚您的数据结构是什么。我假设您希望将节点存储在 unordered_set(或多个集合)中,除此之外,节点还具有 parent 关系。它适用于指针或引用,而不适用于迭代器。您需要的唯一更改是添加一个常量:const Node *parent。如果您需要在将Node 插入到集合中后对其进行更改,您可以通过指针(unique_ptr 等)存储它们,或者考虑将不可变部分作为键的unordered_map

    【讨论】:

      猜你喜欢
      • 2011-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-27
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多