C++ åèæå
- C++11
- C++14
- C++17
- C++20
- C++ ç¼è¯å¨æ¯ææ åµè¡¨
- ç¬ç«ä¸å®¿ä¸»å®ç°
- C++ è¯è¨
- C++ å ³é®è¯
- é¢å¤çå¨
- C++ æ ååºå¤´æä»¶
- å ·åè¦æ±
- åè½ç¹æ§æµè¯ (C++20)
- å·¥å ·åº
- ç¨åºæ¯æå·¥å ·
- std::initializer_list
- 彿°å¯¹è±¡
- std::hash
- std::hash::hash
- std::hash<Key>::operator()
- std::apply
- åºç¹æ§æµè¯å® (C++20)
- std::pair
- std::tuple
- std::optional
- std::any
- std::variant
- æ ¼å¼ååº (C++20)
- std::integer_sequence
- std::exchange
- std::make_from_tuple
- std::launder
- std::to_chars
- std::from_chars
- std::as_const
- std::source_location
- å忰彿°
- std::bitset
- std::cmp_equal, cmp_not_equal, cmp_less, cmp_greater, cmp_less_equal, cmp_greater_equal
- std::in_range
- std::declval
- std::forward
- std::move
- std::move_if_noexcept
- std::chars_format
- std::piecewise_construct_t
- std::piecewise_construct
- std::in_place, std::in_place_type, std::in_place_index, std::in_place_t, std::in_place_type_t, std::in_place_index_t
- 注é
- ç±»åæ¯æï¼åºæ¬ç±»åãRTTIãç±»åç¹æ§ï¼
- æ¦å¿µåº (C++20)
- é误å¤ç
- 卿å å管ç
- æ¥æåæ¶é´å·¥å ·
- å符串åº
- 容å¨åº
- è¿ä»£å¨åº
- èå´åº (C++20)
- ç®æ³åº
- æ°å¼åº
- è¾å ¥/è¾åºåº
- æä»¶ç³»ç»åº
- æ¬å°ååº
- æ£å表达å¼åº
- ååæä½åº
- çº¿ç¨æ¯æåº
- å®éªæ§ C++ ç¹æ§
- æç¨çèµæº
- ç´¢å¼
- std 符å·ç´¢å¼
- åç¨æ¯æ (C++20)
- C++ å ³é®è¯
ä½ç½®ï¼é¦é¡µ > C++ åèæå >å·¥å ·åº > std::hash
std::hash
æ¤æ¨¡æ¿çæ¯ä¸ªç¹å为å¯ç¨ï¼âæ æ±¡æâï¼æä¸ºç¦ç¨ï¼â䏿¯âï¼ãå¯¹äºæ¯ä¸ªæ¢éåºäº¦éç¨æ·æä¾çæ°æ®ç±»åçKeyå¯ç¨ç¹åç彿° std::hash<Key>, ç¹ååå¨ä¸è¢«ç¦ç¨ã被ç¦ç¨ç¹å䏿»¡è¶³æ£å (Hash) ï¼ä¸æ»¡è¶³å½æ°å¯¹è±¡ (FunctionObject) ï¼ä¸ std::is_default_constructible_v ã std::is_copy_constructible_v ã std::is_move_constructible_v ã std::is_copy_assignable_v ã std::is_move_assignable_v å
¨ä¸º false ãæ¢è¨ä¹ï¼å®ä»¬åå¨ä½æ æ³ä½¿ç¨ã
hash 彿°æ¨¡æ¿çå¯ç¨çç¹å (C++17 èµ·)å®ä¹ä¸ä¸ªå®ç°æ£å彿°ç彿°å¯¹è±¡ãæ¤å½æ°å¯¹è±¡çå®ä¾æ»¡è¶³æ£å (Hash) ãç¹å«æ¯å®ä»¬å®ä¹æ»¡è¶³ä¸åæ¡ä»¶ç operator() ï¼
1. æ¥æ¶ Key ç±»åçåä¸ªåæ°
2. è¿åè¡¨ç¤ºåæ°åå¸å¼ç std::size_t ç±»åã
3. è°ç¨æ¶ä¸æåºå¼å¸¸ã
4. 对äºäºä¸ªç¸ççåæ° k1 ä¸ k2 ï¼ std::hash<Key>()(k1) == std::hash<Key>()(k2) ã
5. 对äºäºä¸ªç¸å¼èä¸ç¸ççåæ° k1 ä¸ k2 ï¼ std::hash<Key>()(k1) == std::hash<Key>()(k2) çæ¦çåºé常å°ï¼æ¥è¿ 1.0/std::numeric_limits<std::size_t>::max() ã
åºå½æ°æä¾ç hash çæææ¾å¼åé¨åç¹åå¯é»è®¤æé (DefaultConstructible) ãå¯å¤å¶èµå¼ (CopyAssignable) ãå¯äº¤æ¢ (Swappable) ä¸å¯ææ (Destructible) ãç¨æ·æä¾ç hash ç¹å亦å¿
须满足è¿äºè¦æ±ã
æ åºå ³èå®¹å¨ std::unordered_set ã std::unordered_multiset ã std::unordered_map ã std::unordered_multimap ä»¥è¯¥æ¨¡æ¿ std::hash çç¹å为é»è®¤åå¸å½æ°ã
注解
é¤äºä¸è¿°æå®çæ åµå¤ï¼åå¸å½æ°çå®ç°æ¹å¼æ¯å®ç°å®ä¹çãï¼æ¯å¦ï¼ gcc çå®ç°ï¼ãéè¦æ³¨æï¼æäºåå¸å½æ°çå®ç°è¿äºç®åï¼çè³æ¯ç´æ¥å°å¯¹è±¡æ å°è³èªèº«ãè¿å¯è½ä¼é æä¸¥éçåæãæ¢è¨ä¹ï¼è¿äºåå¸å½æ°å¯ä»¥ç¨äºæ åºå ³è容å¨ï¼ä½å®ä»¬ä¸ä¸å®å®å ¨/æç¢°æã
|
åå¸å½æ°ä» è¦æ±å¨ç¨åºç忬¡æ§è¡ä¸å¯¹åæ ·çè¾å ¥è¿ååæ ·çç»æï¼è¿å 许é¿å 碰ææç»æå¡æ»å»çå çåå¸ã |
(C++14 èµ·) |
没æå¯¹ C å符串çç¹åã std::hash<const char*> 产çæéå¼ï¼å åå°åï¼çåå¸ï¼å®ä¸æ£éªä»»ä½å符æ°ç»çå 容ã
æåç±»å
|
(C++20 å) | ||||||||
æå彿°
| æé åå¸å½æ°å¯¹è±¡ (å ¬å¼æå彿°) | |
| 计ç®åæ°çåå¸ (å ¬å¼æå彿°) |
åºæ¬ç±»åçæ åç¹å
| å®ä¹äºå¤´æä»¶ <functional>
|
||
| template<> struct hash<bool>; template<> struct hash<char>; |
||
|
å¨ä¸è¿°ä¹å¤ï¼æ ååºå¯¹ææï¼æä½ç¨åææ ä½ç¨åï¼æä¸¾ç±»åæä¾ç¹åãå¯ä»¥ï¼ä½ä¸è¦æ±ï¼å®ç°ä¸º std::hash<std::underlying_type<Enum>::type> |
(C++14 èµ·) |
|
æ ååºæä¾ æ¯ä¸ªå£°ææ¨¡æ¿ æ¤æ¨¡æ¿çæ ååºç¹åçææå½æ°å为 noexcept ï¼é¤äº std::hash<std::optional> ã std::hash<std::variant> å std::hash<std::unique_ptr> çæå彿°ã |
(C++17 èµ·) |
åºç±»åçæ åç¹å
| (C++11)(C++20)(C++11)(C++11)(C++11)(C++20)(C++20)(C++20)(C++20)(C++20) |
string çå叿¯æ (类模æ¿ç¹å) |
| (C++11) |
std::error_code çæ£åæ¯æ (类模æ¿ç¹å) |
| (C++11) |
std::bitset çæ£åæ¯æ (类模æ¿ç¹å) |
| (C++11) |
std::unique_ptr çæ£åæ¯æ (类模æ¿ç¹å) |
| (C++11) |
std::shared_ptr çæ£åæ¯æ (类模æ¿ç¹å) |
| (C++11) |
std::type_index çæ£åæ¯æ (类模æ¿ç¹å) |
| (C++11) |
std::vector<bool> çå叿¯æ (类模æ¿ç¹å) |
| (C++11) |
std::thread::id çå叿¯æ (类模æ¿ç¹å) |
| (C++17) |
ç¹å std::hash ç®æ³ (类模æ¿ç¹å) |
| (C++17) |
ç¹å std::hash ç®æ³ (类模æ¿ç¹å) |
| string_view çæ£åæ¯æ (类模æ¿ç¹å) | |
| std::error_condition çå叿¯æ (类模æ¿ç¹å) |
注æï¼å¯¹ std::pair åæ å容å¨ç±»åçç¹åï¼è¿æç»ååå¸çå·¥å
·å½æ°å¯ç¨äº boost.hash
示ä¾
#include <iostream> #include <iomanip> #include <functional> #include <string> #include <unordered_set>  struct S { std::string first_name; std::string last_name; }; bool operator==(const S& lhs, const S& rhs) { return lhs.first_name == rhs.first_name && lhs.last_name == rhs.last_name; }  // èªå®ä¹åå¸è½æ¯ç¬ç«å½æ°å¯¹è±¡ï¼ struct MyHash { std::size_t operator()(S const& s) const { std::size_t h1 = std::hash<std::string>{}(s.first_name); std::size_t h2 = std::hash<std::string>{}(s.last_name); return h1 ^ (h2 << 1); // æä½¿ç¨ boost::hash_combine ï¼è§è®¨è®ºï¼ } };  // std::hash çèªå®ä¹ç¹åè½æ³¨å ¥ namespace std namespace std { template<> struct hash<S> { typedef S argument_type; typedef std::size_t result_type; result_type operator()(argument_type const& s) const { result_type const h1 ( std::hash<std::string>{}(s.first_name) ); result_type const h2 ( std::hash<std::string>{}(s.last_name) ); return h1 ^ (h2 << 1); // æä½¿ç¨ boost::hash_combine ï¼è§è®¨è®ºï¼ } }; }  int main() {  std::string str = "Meet the new boss..."; std::size_t str_hash = std::hash<std::string>{}(str); std::cout << "hash(" << std::quoted(str) << ") = " << str_hash << '\n';  S obj = { "Hubert", "Farnsworth"}; // 使ç¨ç¬ç«ç彿°å¯¹è±¡ std::cout << "hash(" << std::quoted(obj.first_name) << ',' << std::quoted(obj.last_name) << ") = " << MyHash{}(obj) << " (using MyHash)\n or " << std::hash<S>{}(obj) << " (using std::hash) " << '\n';  // èªå®ä¹åå¸ä»¤å¨æ åºå®¹å¨ä¸ä½¿ç¨èªå®ä¹ç±»åå¯è¡ // æ¤ç¤ºä¾å°ä½¿ç¨æ³¨å ¥ç std::hash ç¹åï¼ // è¥è¦ä½¿ç¨ MyHash æ¿ä»£ï¼åå°å ¶ä½ä¸ºç¬¬äºæ¨¡æ¿åæ°ä¼ é std::unordered_set<S> names = {obj, {"Bender", "Rodriguez"}, {"Leela", "Turanga"} }; for(auto& s: names) std::cout << std::quoted(s.first_name) << ' ' << std::quoted(s.last_name) << '\n'; }
å¯è½çè¾åºï¼
hash("Meet the new boss...") = 1861821886482076440
hash("Hubert","Farnsworth") = 17622465712001802105 (using MyHash)
or 17622465712001802105 (using std::hash)
"Leela" "Turanga"
"Bender" "Rodriguez"
"Hubert" "Farnsworth"