Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unordered_map pointer to element's value valid after resize?

If I have an unordered_map<key, someNiceObject>

(note someNiceObject is not a pointer)

I have an API which inserts a new element, then returns a pointer to someNiceObject now in the map.

If I perform further insertions into the map, there could be a capacity change. If that happens is the pointer still valid or not?

I tried reading Basic questions: Pointers to objects in unordered_maps (C++), std::unordered_map pointers/reference invalidation and http://eel.is/c++draft/unord.req#9

and couldn't locate the necessary information

Thanks all

edit: it seems that the pointer would be valid (https://www.thecodingforums.com/threads/do-insert-erase-invalidate-pointers-to-elements-values-of-std-unordered_map.961062/)

though would appreciate a second confirmation from someone here on SO.

like image 949
friartuck Avatar asked Nov 05 '18 06:11

friartuck


People also ask

Are elements sorted in unordered_map?

unordered_map is used to store elements as key,value pairs in non-sorted order.

Is unordered_map initialized to 0?

The value object is value-initialized, not zero-initialized.

What does an unordered_map return if the key does not exist?

Return value the unordered map will try to default initialize mystruct with the key 'x' and assign to my struct. if u wanna avoid this, use . at(key) if it doesn't exist it will throw an out_of_range exception , which you can catch it and handle.

What is the time complexity of unordered_map?

The time complexity of unordered_map operations is O(1) on average.


2 Answers

According to cppreference:

If rehashing occurs due to the insertion, all iterators are invalidated. Otherwise iterators are not affected. References are not invalidated.

Which implies that pointers aren't invalidated either. This is possible because std::unordered_map is conceptually can be thought of as std::vector<std::forward_list<std::pair<Key, Value>>>. And since std::forward_list, like any other linked list, allocates each element separately, changes to the list don't affect the memory location of it's elements.

like image 195
r3mus n0x Avatar answered Nov 02 '22 13:11

r3mus n0x


std::unordered map is unusual in that the iterator invalidation rules do NOT apply to references to elements (excluding removal but what can you do when the item is gone?). A capacity change is not important. The problem is when the unordered map rehashes. Rehashing will invalidate all iterators, but will not invalidate references.

From point 9 of [unord.req] in the C++ Standard (citing n4618 because that's what I have on hand at the moment),

The elements of an unordered associative container are organized into buckets. Keys with the same hash code appear in the same bucket. The number of buckets is automatically increased as elements are added to an unordered associative container, so that the average number of elements per bucket is kept below a bound. Rehashing invalidates iterators, changes ordering between elements, and changes which buckets elements appear in, but does not invalidate pointers or references to elements. For unordered_multiset and unordered_multimap, rehashing preserves the relative ordering of equivalent elements.

emphasis mine

like image 31
user4581301 Avatar answered Nov 02 '22 15:11

user4581301