std::set elements' reference and pointer invariance after insertion

I came across a paragraph on cppreference that I don’t think I understand:

No iterators or references are invalidated. [If the insertion is successful, pointers and references to the element obtained while it is held in the node handle are invalidated, and pointers and references obtained to that element before it was extracted become valid. (since C++17)]

I expect that No iterators or references to already existing objects within the set are invalidated means that the following is correct:

    std::set<person> set{person{"Kate", "Oceanic"}};
    const auto &kate = *set.cbegin();

    std::cout << kate.flight << std::endl;

    // this does not invalidate reference to Kate
    set.insert(person{"John", "Oceanic815"});
    std::cout << kate.flight << std::endl;

But I don’t get what the part for C++17 means: ...pointers and references to the element obtained while it is held in the node handle are invalidated, ... Does node handle refer to an iterator?
... and pointers and references obtained to that element before it was extracted become valid What does exactly become mean here?

The full example:


#include <set>
#include <string>
#include <iostream>

struct person
{
    std::string name;
    std::string flight;

    bool operator<(const person& other) const
    {
        return name < other.name;
    }
};

int main()
{
    std::set<person> set{person{"Kate", "Oceanic"}};
    const auto &kate = *set.cbegin();

    std::cout << kate.flight << std::endl;

    // this does not invalidate Kate
    set.insert(person{"John", "Oceanic815"});
    std::cout << kate.flight << std::endl;

    // is new Kate created within the same address?
    set.insert(person{"Kate", "Oceanic815"});
    std::cout << kate.flight << std::endl;

    return 0;
}

>Solution :

Does node handle refer to an iterator?

No.

A "node handle", introduced in C++17, refers to the data structure internal to a std::set used to hold a single element. It’s what the std::set will allocate from the free store to hold the element and any related data structures, such as pointers and red/black flags.

This concept allows elements to be removed from a set (via std::set::extract) without triggering a memory deallocation, and added to a set without triggering a memory allocation.

and pointers and references obtained to that element before it was extracted become valid

What does exactly become mean here?

It means that pointers and references to an element in a node handle are invalid when they are extracted, but they are valid once again when that same node handle is inserted back into a set.

Leave a Reply