简体   繁体   中英

Pointer/Reference to element in std::unordered_set

im using a std::unordered_set to store my data object. But now i want to create a pointer/reference to them, for example (without hash function ... ):

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

is it possible to use a std::unordered_set<Node>::const_iterator ? Im not sure how to figure out this information if (without removing elements!) the iterator "ordering" changes ?

UPDATE with more details for better understanding:

Ive choosed std::unordered_set because of the constant lookup time. To improve my C++ skills it would good to know what to change.

#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) );    
}

You can have pointers to the Node objects inside of the unordered_set . However these pointer must be Node const* (ie, const ).

Even if an insertion is made to the unordered_set the pointers will not be invalidated. For example you could store these pointers in another unordered_set<Node const*> as:

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

Iterators in unordered containers get invalidated when rehashing happens during an insert. I'd not try to predict or avoid rehashing. As long as you don't insert new items, iterators stay valid. You may erase existing items.

Note that values don't move even if rehashing occurs. Pointers and references aren't invalidated until you remove that particular item. This means that you can do Node* parent or like that.

It's unclear what is your data structure. I assume that you want to store nodes in an unordered_set (or several sets), and nodes have parent relation in addition to that. It will work fine with pointers or references and not with iterators. The only change you need is add one const: const Node *parent . If you need to change Node after inserting it in a set, you may either store them by pointer ( unique_ptr , etc.), or consider unordered_map with immutable part as a key.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM