C++ - Containers
https://en.cppreference.com/w/cpp/container
TL;DR
std::vector
should be the default option for sequencesabsl::flat_hash_map
andabsl::flat_hash_set
should be used for most associative containers.
Traits
Pointer Stability
Pointer stability / Reference stability: if a pointer / reference to a key or value in a map is guaranteed to remain valid for the lifetime of the map.
All elements of a container that does not guarantee pointer stability may be invalidated when the container is inserted to (flat_hash_map
and btree_map
) or removed from (btree_map
only).
Saying that a container has pointer stability is the same as saying that it doesn't move elements in memory; their addresses do not change. Pointer stability /invalidation is the same as reference stability / invalidation.
Stable Iteration Order
Stable iteration order: if the order of the elements is consistent across different instances of a container and different runs of the same binary.
For example: std::unordered_set<string> container = {"a", "b", "c"};
or absl::flat_hash_set
does not always produce the same output if calling absl::StrJoin(container, ",");
.
Choice of maps
- Does not require pointer-stability (ordering is not required): use
absl::flat_hash_map
(A "flat" map is backed by a contiguous array) - Requires pointer-stability of values (but not keys): use
absl::flat_hash_map<Key, std::unique_ptr<Value>>
. - Requires pointer-stability of both keys and values (ordering is not required): use
absl::node_hash_map
- If sorted order is required Use
absl::btree_map
(pointer stability is not required) std::map
provides ordering and pointer stability
flat_hash_map and flat_hash_set
absl::flat_hash_map
and absl::flat_hash_set
are the recommended unordered containers for general use.
They are more efficient but don't provide guarantees on pointer or iterator stability that std::unordered_map
does. The standard maps guarantee that elements that have been inserted are never moved, so that pointers and references to them stay valid so long as the element remains present in the map.
Use absl::node_hash_map
and absl::node_hash_set
for guaranteed pointer stability. Or use unique_ptr
like absl::flat_hash_map<std::string, std::unique_ptr<std::string>>