命名空間
變體
動作

std::hash

出自 cppreference.com
< cpp‎ | 工具
 
 
 
 
定義於標頭 <bitset>
定義於標頭檔 <coroutine>
定義於標頭檔 <chrono>
(C++26 起)
定義於標頭檔 <filesystem>
定義於標頭檔 <functional>
定義於標頭檔 <memory>
定義於標頭檔 <optional>
定義於標頭檔 <stacktrace>
定義於標頭檔 <string>
定義於標頭檔 <string_view>
定義於標頭檔 <system_error>
定義於標頭檔 <text_encoding>
定義於標頭檔 <thread>
定義於標頭 <typeindex>
定義於標頭 <variant>
定義於標頭檔 <vector>
template< class Key >
struct hash;
(C++11 起)

無序關聯容器 std::unordered_setstd::unordered_multisetstd::unordered_map 以及 std::unordered_multimap 使用 std::hash 樣板的特例化作為預設雜湊函式。

給定型別 Key,每個 std::hash<Key> 特例化要么是已啟用 (enabled),要么是已停用 (disabled) 

  • std::hash<Key> 未由程式或使用者提供,則它被停用。
  • 否則,若滿足以下所有條件,則 std::hash<Key> 為已啟用:
  • 滿足以下所有要求:
  • 給定以下值
  • h,一個 std::hash<Key> 型別的物件。
  • k1k2,兩個 Key 型別的物件。
滿足以下所有要求:
  • k1 == k2true,則 h(k1) == h(k2) 也為 true
  • 除非 std::hash<Key>程式定義的特例化,否則 h(k1) 絕不會拋出例外。
  • 否則,std::hash<Key> 為已停用。

已停用的特例化不滿足 Hash,不滿足 FunctionObject,且以下值皆為 false

換句話說,它們存在,但無法使用。

目錄

巢狀型別

名稱 定義
argument_type (C++17 起棄用) Key
result_type (C++17 起棄用) std::size_t
(直到 C++20)

[編輯] 成員函式

建構一個雜湊函式物件
(公開成員函式)
計算引數的雜湊值
(公開成員函式)

[編輯] 標準函式庫特例化

每個宣告 std::hash 樣板的標頭檔,同時也為以下型別提供了 std::hash 的已啟用特例化:

除此之外,某些標頭檔也為函式庫型別提供了其他的 std::hash 已啟用特例化(見下方)。

對於標準函式庫提供的所有 std::hash 特例化,除下列之外,其所有成員函式皆為 noexcept

(C++26 起)
(自 C++17 起)

[編輯] 函式庫型別的特例化

std::coroutine_handle 的雜湊支援
(類別樣板特例化) [編輯]
std::error_code 的雜湊支援
(類別樣板特例化) [編輯]
std::error_condition 的雜湊支援
(類別樣板特例化) [編輯]
std::stacktrace_entry 的雜湊支援
(類別樣板特例化) [編輯]
std::basic_stacktrace 的雜湊支援
(類別樣板特例化) [編輯]
std::optional 的雜湊支援
(類別範本特化) [編輯]
std::variant 的雜湊支援
(類別樣板特例化) [編輯]
std::monostate 的雜湊支援
(class template specialization)
std::bitset 的雜湊支援
(類別樣板特例化) [編輯]
std::unique_ptr 的雜湊支援
(類別範本特化) [編輯]
std::shared_ptr 的雜湊支援
(類別範本特化) [編輯]
std::type_index 的雜湊支援
(類別樣板特例化) [編輯]
對字串的雜湊 (hash) 支援
(類別樣板特化) [編輯]
字串檢視 (string views) 的雜湊支援
(類別樣板特例化) [編輯]
std::text_encoding 的雜湊支援
(類別樣板特例化) [編輯]
std::vector<bool> 的雜湊支援
(class template specialization)
std::filesystem::path 的雜湊支援
(類別樣板特例化) [編輯]
std::thread::id 的雜湊支援
(類別樣板特例化) [編輯]
std::chrono::duration 的雜湊支援
(class template specialization)
std::chrono::time_point 的雜湊支援
(class template specialization)
std::chrono::day 的雜湊支援
(class template specialization)
std::chrono::month 的雜湊支援
(class template specialization)
std::chrono::year 的雜湊支援
(class template specialization)
std::chrono::weekday 的雜湊支援
(class template specialization)
std::chrono::weekday_indexed 的雜湊支援
(class template specialization)
std::chrono::weekday_last 的雜湊支援
(class template specialization)
std::chrono::month_day 的雜湊支援
(class template specialization)
std::chrono::month_day_last 的雜湊支援
(class template specialization)
std::chrono::month_weekday 的雜湊支援
(class template specialization)
std::chrono::month_weekday_last 的雜湊支援
(class template specialization)
std::chrono::year_month 的雜湊支援
(class template specialization)
std::chrono::year_month_day 的雜湊支援
(class template specialization)
std::chrono::year_month_day_last 的雜湊支援
(class template specialization)
std::chrono::year_month_weekday 的雜湊支援
(class template specialization)
std::chrono::year_month_weekday_last 的雜湊支援
(class template specialization)
std::chrono::zoned_time 的雜湊支援
(class template specialization)
std::chrono::leap_second 的雜湊支援
(class template specialization)

[編輯] 備註

實際的雜湊函式取決於實作,除了上述指定的要求外,不需滿足任何其他品質標準。值得注意的是,某些實作使用簡單(恆等)雜湊函式,將整數映射至其自身。換句話說,這些雜湊函式旨在與無序關聯容器搭配使用,而非例如加密用途的雜湊。

雜湊函式僅被要求在程式的單次執行中,對相同輸入產生相同的結果;這允許使用加鹽雜湊(salted hashes)來防止拒絕服務攻擊。

沒有針對 C 字串的特例化。std::hash<const char*> 產生的是指標值(記憶體位址)的雜湊,它不會檢查字元陣列的內容。

std::pair 與標準容器型別的額外特例化,以及用於組合雜湊的實用工具函式,可在 boost::hash 中找到。

[編輯] 範例

#include <cstddef>
#include <functional>
#include <iomanip>
#include <iostream>
#include <string>
#include <unordered_set>
 
struct S
{
    std::string first_name;
    std::string last_name;
    bool operator==(const S&) const = default; // since C++20
};
 
// Before C++20.
// bool operator==(const S& lhs, const S& rhs)
// {
//     return lhs.first_name == rhs.first_name && lhs.last_name == rhs.last_name;
// }
 
// Custom hash can be a standalone function object.
struct MyHash
{
    std::size_t operator()(const S& s) const noexcept
    {
        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); // or use boost::hash_combine
    }
};
 
// Custom specialization of std::hash can be injected in namespace std.
template<>
struct std::hash<S>
{
    std::size_t operator()(const S& s) const noexcept
    {
        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); // or use 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) << ") =\t" << str_hash << '\n';
 
    S obj = {"Hubert", "Farnsworth"};
    // Using the standalone function object.
    std::cout << "hash(" << std::quoted(obj.first_name) << ", "
              << std::quoted(obj.last_name) << ") =\t"
              << MyHash{}(obj) << " (using MyHash) or\n\t\t\t\t"
              << std::hash<S>{}(obj) << " (using injected specialization)\n";
 
    // Custom hash makes it possible to use custom types in unordered containers.
    // The example will use the injected std::hash<S> specialization above,
    // to use MyHash instead, pass it as a second template argument.
    std::unordered_set<S> names = {obj, {"Bender", "Rodriguez"}, {"Turanga", "Leela"}};
    for (auto const& s: names)
        std::cout << std::quoted(s.first_name) << ' '
                  << std::quoted(s.last_name) << '\n';
}

可能輸出

hash("Meet the new boss...") =  10656026664466977650
hash("Hubert", "Farnsworth") =  12922914235676820612 (using MyHash) or
                                12922914235676820612 (using injected specialization)
"Bender" "Rodriguez"
"Turanga" "Leela"
"Hubert" "Farnsworth"

[編輯] 缺陷報告

下列更改行為的缺陷報告追溯應用於之前的 C++ 標準。

DR 應用於 出版時的行為 正確的行為
LWG 2119 C++11 缺少了針對擴充整數型別的特例化 提供
LWG 2148 C++11 缺少了針對列舉型別的特例化 提供
LWG 2543 C++11 std::hash 可能對 SFINAE 不友善 改為對 SFINAE 友善
LWG 2817 C++11 缺少了針對 std::nullptr_t 的特例化 提供
English Deutsch 日本語 中文(简体) 中文(繁體)