Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ stl unordered_map implementation, reference validity

For both std::map and std::tr1::unordered_map, I see from the standard that:

References to elements in the unordered_map container remain valid in all cases, even after a rehash.

How are they doing that (implementation-wise)? Are they maintaining all the entries as a kind of linked list and then the hash-table just stores pointers to the elements?

like image 371
Switch Avatar asked Jul 05 '12 03:07

Switch


People also ask

How is STL unordered_map implemented?

Internally unordered_map is implemented using Hash Table, the key provided to map is hashed into indices of a hash table which is why the performance of data structure depends on the hash function a lot but on average, the cost of search, insert, and delete from the hash table is O(1).

Does unordered_map maintain insertion order?

No. It's called "unordered" for a reason. If you need to maintain an order of insertion, you've chosen an unsuitable data structure.

How Unordered_set is implemented?

An unordered_set is implemented using a hash table where keys are hashed into indices of a hash table so that the insertion is always randomized.


1 Answers

Yes, linked lists are involved, although not quite in the way you suggest.

The 2011 standard says (23.2.5 para 8), "The elements of an unordered associative container are organized into buckets. Keys with the same hash code appear in the same bucket."

Within each bucket, the elements are in a linked list (a separate list for each bucket, not one big list for the whole container). When the container is rehashed, the elements will be assigned to new buckets, but the pointers to each element remain valid. The linked list in each new bucket is assembled from pointers to the existing elements that end up in that bucket.

Iterators are invalidated by a rehash, since an iterator needs to hold pointers to both the element and its bucket (so it can be stepped from the last element of one bucket to the first element of the next). The element pointer remains valid, so existing pointers and references to an element are still valid, but the bucket pointer is invalidated by a rehash, so the iterator isn't usable.

(This is also why unordered containers only support forward iterators, instead of the bidirectional iterators supported by the ordered associative containers. The elements of each bucket are in a singly linked list, so you can't step backwards through them.)

like image 191
Ross Smith Avatar answered Oct 03 '22 02:10

Ross Smith