On 2017-01-23, Christopher J. Pisz <
cp...@austin.rr.com> wrote:
[snip]
> so, std::map is implemented as a tree and std::unordered_map is
> implemented as a hastable?
>
> What are the differences, advantages, etc?
Well! The main answer is implicit in the name. std::map, as a tree,
can be traversed in order. What do I mean by order?
One of the parameters to std::map is a functor class that, when called
with two Keys, will return true if the first is less than the
second. By default this functor is std::less specialized on the key
type.
When you iterate over a std::map, you traverse the elements in order
from Least to Greatest. std::map inserts or looks up elements in
logarithmic time. It's implemented as a tree. A Red-Black tree
specifically in GNU libstdc++ and CLang libc++.
std::unordered_map is a hash table. Instead of a functor telling
whether one key is less than another, it takes one functor that hashes
objects (taking an object it returns a value convertible to
std::size_t) and another defining equivalence that returns true if two
supplied objects are equal.
By default it uses std::hash and std::equal_to specialized on the Key
type. std::unordered_map does lookups and insertions, on average, in
constant time. If your hash function is really bad or your object
distribution is really pathological, it degrades to linear. it does
/not/ traverse objects from least to greatest and there's basically
nothing useful you can say about the order of traversal except that
you do traverse all objects.
If you don't need ordered traversal, you likely want a
std::unordered_map. As always, if performance is critical, benchmark
your use-case with your library.
If you wish to avoid allocations and you can insert your items in
order, you may want boost::container::flat_map.
If the entire set of keys will be known at compile time, consider
using a Perfect Hash Function like those generated by gperf.