是否需要为自定义类型创建自己的哈希函数?我可以使用unordered_set吗?
答案 0 :(得分:14)
标准库包含std::hash<T>
的基本类型,指针和std::string
(或更确切地说,std::basic_string
的所有特化)的特化。
不幸的是,库不包含以下重要的新旧组合函数,但它是Boost的一部分,您应将其复制到代码中:
template <class T>
inline void hash_combine(std::size_t & seed, const T & v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
使用此函数,您可以散列对,元组,数组以及任何类型的范围自身可以清除的元素。浏览Boost源代码,了解许多示例和有用的实现。显然,您可以使用此函数为您自己的类型创建哈希函数。例如,这里是一对哈希:
template<typename S, typename T> struct pair_hash<std::pair<S, T>>
{
inline std::size_t operator()(const std::pair<S, T> & v) const
{
std::size_t seed = 0;
hash_combine(seed, v.first);
hash_combine(seed, v.second);
return seed;
}
};
请注意,哈希组合不会产生良好的哈希值。结果具有非常差的统计质量(例如,创建散列冲突非常容易)。好的散列需要能够看到所有原始输入位,并且不能通过部分散列来计算。 (这就是为什么目前的标准库没有更好的解决方案;没有人能够提出令人满意的设计。)
答案 1 :(得分:9)
是的,您需要编写自己的哈希函数。这听起来并不像听起来那么糟糕:如果你的班级有任何你认为合适的可清除成员,你就可以返回该成员的哈希值。
您可以通过专门化std::hash
或通过显式传递哈希类作为模板参数来提供此哈希。