Professional C__ - Marc Gregoire [216]
unordered_map {1, "Item 1"}, {2, "Item 2"}, {3, "Item 3"}, {4, "Item 4"} }; for (auto& p : m) cout << p.first << " = " << p.second << endl; Code snippet from unordered_map\unordered_map.cpp The following table summarizes the differences between a map and an unordered_map. OPERATION map unordered_map at() x x begin() x x bucket() x bucket_count() x bucket_size() x cbegin() x x cend() x x clear() x x count() x x crbegin() x crend() x emplace() x x emplace_hint() x x empty() x x end() x x equal_range() x x erase() x x find() x x insert() x x iterator / const_iterator x x load_factor() x local_iterator / const_local_iterator x lower_bound() x max_bucket_count() x max_load_factor() x operator[] x x rbegin() x rehash() x rend() x reserve() x reverse_iterator / const_reverse_iterator x size() x x swap() x x upper_bound() x As with a normal map, all keys in an unordered_map should be unique. The preceding table includes a number of hash specific methods. For example, load_factor() returns the average number of elements per bucket to give you an indication on the number of collisions. The bucket_count() method returns the number of buckets in the container. It also provides a local_iterator and const_local_iterator allowing you to iterate over the elements in a single bucket; but, these may not be used to iterate across buckets. The bucket(key) method returns the index of the bucket that contains the given key; begin(n) returns a local_iterator referring to the first element in the bucket with index n, and end(n) returns a local_iterator referring to one-past-the-last element in the bucket with index n. The example in the next section will make things more clear on how to use these methods. unordered_map Example: Phone Book The following example uses an unordered_map to represent a phone book. The name of a person will be the key while the phone number will be the value associated with that key. template void printMap(const T& m) { for (auto& p : m) { cout << p.first << "(Phone: " << p.second << ")" << endl; } cout << "-------" << endl; } int main() { // Create a hash table. unordered_map um.insert({ {"Marc G.", "123-456789"}, {"Zulija N.", "987-654321"}, {"Scott K.", "654-987321"} }); printMap(um); // Add/remove some phone numbers. um.insert(make_pair("John D.", "321-987654")); um["Johan G."] = "963-258147"; um["Freddy K."] = "999-256256"; um.erase("Freddy K."); printMap(um); // Find the bucket index for a specific key. int bucket = um.bucket("Marc G."); cout << "Marc G. is in bucket " << bucket << " which contains the following " << um.bucket_size(bucket) << " elements:" << endl; // Get begin and end iterators for the elements in this bucket. // 'auto' is being used here. The compiler will derive the type // of both iterators as // unordered_map auto liter = um.cbegin(bucket); auto literEnd = um.cend(bucket); while (liter != literEnd) { cout << "\t" << liter->first << "(Phone: " << liter->second << ")" << endl; ++liter; } cout << "-------" << endl; // Print some statistics about the hash table cout << "There are " << um.bucket_count() << " buckets." << endl; cout << "Average number of elements in a bucket is " << um.load_factor() << endl; return 0; } Code snippet from PhoneBook\PhoneBook.cpp This example uses a lot of C++11 features: unordered_map, range-based for loop, auto and initializer_lists. The output of this code is as follows: Zulija N.(Phone: 987-654321) Marc G.(Phone: