1

If a std::unordered_map<int,...> was to stay roughly the same size but continually add and remove items, would it continually allocate and free memory or cache and reuse the memory (ie. like a pool or vector)? Assuming a modern standard MS implementation of the libraries.

Nicholas
  • 1,392
  • 16
  • 38
  • 1
    Have a look at the source code of your implementation. – Richard Critten Sep 24 '16 at 09:48
  • The standard containers are supposed to use their allocator parameter to manage the memory. They should not try to out-guess the algorithm used there and hold an additional cache of reusable memory blocks. – Bo Persson Sep 24 '16 at 10:26

1 Answers1

1

The standard is not specific about these aspects, so they are implementation defined. Most notably, a caching behaviour like you describe is normally achieved by using a custom allocator (e.g. for a memory pool allocator) so it should normally be decoupled from the container implementation.

The relevant bits of the standard, ~p874 about unordered containers:

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.

and insert:

The insert and emplace members shall not affect the validity of iterators if (N+n) <= z * B, where N is the number of elements in the container prior to the insert operation, n is the number of elements inserted, B is the container’s bucket count, and z is the container’s maximum load factor

You could read between the lines and assume that since iterator validity is not affected, probably no memory allocations will take place. Though this is by no means guaranteed (e.g. if the bucket data structure is a linked list, you can append to it without invalidating iterators). The standard doesn't seem to specify what should happen when an element is removed, but since it couldn't invalidate the constraint above I don't see a reason to deallocate memory.

The easiest way to find out for sure for your specific implementation is to read the source or profile your code. Alternatively you can try to take control of this behaviour (if you really need to) by using the rehash and resize methods and tuning the map's load_factor.

paul-g
  • 3,797
  • 2
  • 21
  • 36
  • unordered_map doesn't guarantee iterator stability. It provides pointer stability instead. This means allocation/deallocation on every insertion/removal of the element. – Evgeny Lazin Oct 13 '19 at 10:50
  • *normally achieved by using a custom allocator* - AFAIK it is impossible to know at compile time the size of the internal node's type (same for `std::set` and `std::map` https://stackoverflow.com/q/22951378/9363996). Since you can't reliably know the size of the node, hence I find it really hard to implement a pool allocator for `node`. – Sergey Kolesnik Mar 08 '23 at 12:49