std::hash în C++

Obiect-funcție care transformă o valoare într-un număr (hash), folosit de unordered_map și unordered_set.

Sintaxă
#include <functional>
std::size_t h = std::hash<T>{}(valoare);

Ce face std::hash

std::hash<T>{}(x) returnează un std::size_t calculat din x. Valori egale dau mereu același hash; valori diferite dau de obicei hash-uri diferite. Containerele std::unordered_map și std::unordered_set îl folosesc ca să găsească repede elementele.

Există specializări pentru numere, pointeri, std::string, std::string_view, std::optional etc. Valorile exacte depind de implementare (aici, libc++): nu le salva în fișiere și nu te baza pe ele între compilatoare.

Pentru tipurile tale, ca să le folosești drept chei în unordered_map, scrii o specializare std::hash<TipulTau>.

Ce returnează

Un număr de tip std::size_t.

Exemple

Exemplul 1: Hash-ul unor valori

Rezultatul este cel produs de libc++, care pentru int returnează chiar numărul; alte biblioteci (libstdc++, MSVC) pot da alte valori, mai ales pentru șiruri.

#include <functional>
#include <print>
#include <string>

int main() {
    std::hash<std::string> h;
    std::println("{}", h("Ana") == h("Ana"));
    std::println("{}", h("Ana") == h("ana"));
    std::println("hash(42) = {}", std::hash<int>{}(42));
}

Rezultat

true
false
hash(42) = 42

Exemplul 2: Tip propriu ca cheie în unordered_set

#include <cstddef>
#include <functional>
#include <print>
#include <string>
#include <unordered_set>

struct Punct {
    int x, y;
    bool operator==(const Punct&) const = default;
};

template <>
struct std::hash<Punct> {
    std::size_t operator()(const Punct& p) const noexcept {
        std::size_t h1 = std::hash<int>{}(p.x);
        std::size_t h2 = std::hash<int>{}(p.y);
        return h1 ^ (h2 << 1);
    }
};

int main() {
    std::unordered_set<Punct> vizitate{{0, 0}, {1, 2}};
    vizitate.insert({1, 2});   // există deja
    std::println("puncte unice: {}", vizitate.size());
    std::println("(1, 2) vizitat: {}", vizitate.contains({1, 2}));
}

Rezultat

puncte unice: 2
(1, 2) vizitat: true

Greșeli frecvente

  • Definești std::hash pentru tipul tău, dar nu și operator==. unordered_map are nevoie de amândouă.
  • Folosești std::hash pentru parole sau semnături. Nu este o funcție criptografică; pentru securitate folosește o bibliotecă specializată.

Comenzi înrudite

  • std::unordered_map: Dicționar bazat pe tabelă hash: căutare în timp mediu constant, dar fără o ordine anume a elementelor.
  • std::unordered_set: Mulțime de valori unice bazată pe hash: verificare „există?” în timp mediu constant, fără ordine.
  • std::less: Obiecte-funcție pentru operatori: less (<), greater (>), plus (+), folosite la sortări și containere.