C++11增加了无序容器unordered_map/unordered_multimap和unordered_set/unordered_multiset,由于这些容器中的元素是不排序的,因此,比有序容器map/multimap和set/multiset效率更高。map和set内部是红黑树,在插入元素时会自动排序,而无序容器内部是散列表(Hash Table),通过哈希(Hash),而不是排序来快速操作元素,使得效率更高。由于无序容器内部是散列表,因此无序容器的key需要提供hash_value函数,其他用法和map/set的用法是一样的。不过对于自定义的key,需要提供Hash函数和比较函数。代码清单2-6是无序容器的基本用法。
代码清单2-6 无序容器的基本用法
#include <unordered_map> #include <vector> #include <bitset> #include <string> #include <utility> struct Key { std::string f?irst; std::string second; }; struct KeyHash { std::size_t operator()(const Key& k) const { return std::hash<std::string>()(k.f?irst) ^ (std::hash<std::string>()(k.second) << 1); } }; struct KeyEqual { bool operator()(const Key& lhs, const Key& rhs) const { return lhs.f?irst == rhs.f?irst && lhs.second == rhs.second; } }; int main() { // default constructor: empty map std::unordered_map<std::string, std::string> m1; // list constructor std::unordered_map<int, std::string> m2 = { {1, "foo"}, {3, "bar"}, {2, "baz"}, }; // copy constructor std::unordered_map<int, std::string> m3 = m2; // move constructor std::unordered_map<int, std::string> m4 = std::move(m2); // range constructor std::vector<std::pair<std::bitset<8>, int>> v = { {0x12, 1}, {0x01,-1} }; std::unordered_map<std::bitset<8>, double> m5(v.begin(), v.end()); // constructor for a custom type std::unordered_map<Key, std::string, KeyHash, KeyEqual> m6 = { { {"John", "Doe"}, "example"}, { {"Mary", "Sue"}, "another"} }; }
对于基本类型来说,不需要提供Hash函数和比较函数,用法上和map/set一样,对于自定义的结构体,就稍微复杂一些,需要提供函数和比较函数。