25

C++11's unordered_map's default constructor looks like this:

explicit unordered_map( size_type bucket_count = /*implementation-defined*/,
                    const hasher& hash = hasher(),
                    const key_equal& equal = key_equal(),
                    const allocator_type& alloc = allocator_type() );

I want to create an unordered_map with a custom hasher function, but it's the second argument to the constructor.

What bucket count should I use? Is there a magic value I can use to tell the container to decide for itself? Otherwise, is there a heuristic I can use to guesstimate a good bucket number based on something like the number of keys I expect my map to contain? Should I even care?

zneak
  • 134,922
  • 42
  • 253
  • 328

2 Answers2

19

I wouldn't worry too much about it.

The container guarantees the bucket count will be at least the value you provide, i.e. it will increase it if needed. You could pass zero as the bucket count and the implementation will either do something like std::max(count, 10) and override the zero value, or it will just rehash on the first insertion.

Another alternative would be to copy the value from a default-constructed object:

H hasher;
unordered_map<K,T,H,P> m{ unordered_map<K,T,H,P>{}.bucket_count(), hasher };

This will set the bucket count to whatever the implementation's default is (but does require the H hash function type to be DefaultConstructible.)

FWIW GCC's unordered_map uses 10 as the default for the constructor you showed (so that's probably a reasonable default too) and uses 0 for the constructors taking a pair of iterators or an initializer_list.

zneak
  • 134,922
  • 42
  • 253
  • 328
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Good trick. Didn't think about that. Thanks for looking into it. – zneak Jan 06 '13 at 16:28
  • 3
    Are you sure about `std::min`? If you want at least 10 elements, the formula is `std::max(count, 10)`. – fredoverflow Jan 06 '13 at 18:21
  • Question and answer have been copy/pasted to [https://coderedirect.com](https://coderedirect.com/questions/391660/what-should-i-pass-to-unordered-maps-bucket-count-argument-if-i-just-want-to-sp) without references... – Jarod42 Nov 08 '21 at 16:10
  • @Jarod42 What is that site?! I found several other copies of SO answers there - including one of my own where I go by the name Alex Chernilov :-) – Ted Lyngmo Nov 08 '21 at 16:46
  • @TedLyngmo: I don't know, found in by hazard. I didn't find relationship between SO and that site, so warn. (The only reference I found on SO are answer which references answer from that site). – Jarod42 Nov 08 '21 at 16:52
  • @Jarod42 Jeez ... and the copies seems to have been put there pretty recently too so perhaps they have just gotten started with this shameless behavior. Yeah, warnings will be issued whenever appropriate! "_Code Redirect is the largest, most trusted online community for developers to learn, share their knowledge, and build their careers_" - what a joke! – Ted Lyngmo Nov 08 '21 at 16:57
2

One of the template parameters for unordered_map is the hash function. If you specify your hash function object there you can leave the constructor parameters at their default settings.

mike__t
  • 979
  • 5
  • 6
  • 2
    While I agree with you, you might specify the *type* of the hasher as a template argument, but still need to provide a specific hasher object to the `unordered_map` at construction if you wanted to do something fancy (for example, if your hasher was a universal family of hash functions and you needed to specify which one of those hash functions to use). – templatetypedef Jan 06 '13 at 05:23
  • Rapptz suggested that on the C++ chat. It *does* work for my purposes since I was just going to pass a function pointer (so wrapping it in a struct is no biggie), and it's definitely worth mentioning, but as @templatetypedef says, it doesn't really help people who really have to give a bucket count. – zneak Jan 06 '13 at 05:38