2

I would like to use pointers to resources stored in an std::map as handles to the resource but for this to work the std::map cannot move any of its contained elements due to insertion/deletion from the map. For example:

class Resource { ... }
std::map<std::string, Resource> resources;

resources["one"] = Resource( ... );
Resource *handle = &resources["one"];

resources["two"] = Resource( ... );
handle->doSomething(); // Is handle guaranteed to still point to the same resource?

I cannot find any documentation that states whether elements can be moved or not, std::map can contain an uncopyable and unmovable type however I want to be sure this isn't some intended adaption to such a type.

EDD
  • 2,070
  • 1
  • 10
  • 23
  • I would guess anything that [invalidates an iterator](https://stackoverflow.com/q/6438086/10957435) would invalidate a pointer, but that is just a guess here. –  Feb 07 '20 at 01:37
  • See [this answer](https://stackoverflow.com/a/1135582/10957435). –  Feb 07 '20 at 01:40
  • AFAIK `std::map` stores node handles and not the elements directly. Inserting a new element should not change the actual location of the element itself but might invalidate references to any node handle. Take this with a grain of salt though – Sebastian Hoffmann Feb 07 '20 at 01:41

1 Answers1

2

From the C++ standard: a std::map is an associative container:

Class template map overview [map.overview]

A map is an associative container that supports unique keys...

The shown code uses the [] operator to modify the map, which is specified in terms of try_emplace():

26.4.4.3 map element access [map.access]

T& operator[](const key_type& x);

Effects: Equivalent to:

return try_emplace(x).first->second;

One of the requirements of all associative containers is that neither the insert nor the emplace members invalidate any existing iterators and references to the container, and erase invalidates only the affected elements:

26.2.6 Associative containers [associative.reqmts]

The insert and emplace members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.

In other words, your handle remains valid, and is not affected by any other changes to the same map. Only actual removal from the map container invalidates any references or pointers, and only to the elements in the container that are affected by the erase.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148