Viene utilizzato l'oggetto funzione std::hash<>
.
Le specializzazioni standard esistono per tutti i tipi incorporati e alcuni altri tipi di libreria standard come std::string
e std::thread
. Vedi il link per l'elenco completo.
Per altri tipi da utilizzare in un std::unordered_map
, è necessario specializzarsi su std::hash<>
o creare il proprio oggetto funzione.
La possibilità di collisione è completamente dipendente dall'implementazione, ma considerando il fatto che gli interi sono limitati tra un intervallo definito, mentre le stringhe sono teoricamente infinitamente lunghe, direi che c'è una possibilità molto migliore di collisione con le stringhe.
Per quanto riguarda l'implementazione in GCC, la specializzazione per i tipi incorporati restituisce semplicemente il modello di bit. Ecco come vengono definiti in bits/functional_hash.h
:
/// Partial specializations for pointer types.
template<typename _Tp>
struct hash<_Tp*> : public __hash_base<size_t, _Tp*>
{
size_t
operator()(_Tp* __p) const noexcept
{ return reinterpret_cast<size_t>(__p); }
};
// Explicit specializations for integer types.
#define _Cxx_hashtable_define_trivial_hash(_Tp) \
template<> \
struct hash<_Tp> : public __hash_base<size_t, _Tp> \
{ \
size_t \
operator()(_Tp __val) const noexcept \
{ return static_cast<size_t>(__val); } \
};
/// Explicit specialization for bool.
_Cxx_hashtable_define_trivial_hash(bool)
/// Explicit specialization for char.
_Cxx_hashtable_define_trivial_hash(char)
/// ...
La specializzazione per std::string
è definito come:
#ifndef _GLIBCXX_COMPATIBILITY_CXX0X
/// std::hash specialization for string.
template<>
struct hash<string>
: public __hash_base<size_t, string>
{
size_t
operator()(const string& __s) const noexcept
{ return std::_Hash_impl::hash(__s.data(), __s.length()); }
};
Alcuni ulteriore ricerca ci porta a:
struct _Hash_impl
{
static size_t
hash(const void* __ptr, size_t __clength,
size_t __seed = static_cast<size_t>(0xc70f6907UL))
{ return _Hash_bytes(__ptr, __clength, __seed); }
...
};
...
// Hash function implementation for the nontrivial specialization.
// All of them are based on a primitive that hashes a pointer to a
// byte array. The actual hash algorithm is not guaranteed to stay
// the same from release to release -- it may be updated or tuned to
// improve hash quality or speed.
size_t
_Hash_bytes(const void* __ptr, size_t __len, size_t __seed);
_Hash_bytes
è un funzione esterna da libstdc++
. Un po 'più alla ricerca mi ha portato a this file, in cui si afferma:
// This file defines Hash_bytes, a primitive used for defining hash
// functions. Based on public domain MurmurHashUnaligned2, by Austin
// Appleby. http://murmurhash.googlepages.com/
Così il GCC algoritmo predefinito hashing usa per le stringhe è MurmurHashUnaligned2.
Penso che sia all'altezza dello standard. Non sei sicuro di cosa sia unorderd_map. – Joel
unordered_map è come tabella hash ... Le funzioni di hash predefinite cambiano in C++ 98 vs C++ 11? – Medicine
Hai taggato questo C++ 11, ma hai chiesto informazioni su TR1. Cos'è questo? –