【发布时间】:2012-04-01 12:44:57
【问题描述】:
我是否需要为自定义类型创建自己的哈希函数? unordered_set 没有我可以使用的默认值吗?
【问题讨论】:
-
哈希
Foo的“默认方式”是什么?
标签: c++ visual-c++
我是否需要为自定义类型创建自己的哈希函数? unordered_set 没有我可以使用的默认值吗?
【问题讨论】:
Foo的“默认方式”是什么?
标签: c++ visual-c++
标准库包含用于基本类型、指针和std::string 的std::hash<T> 特化(或者更确切地说,对于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;
}
};
但请注意,哈希组合不会产生好的哈希值。结果的统计质量很差(例如,很容易产生哈希冲突)。良好的散列需要能够看到所有原始输入位,并且不能通过部分散列分解。 (这就是为什么在当前的标准库中没有更好的解决方案;没有人能够提出令人满意的设计。)
【讨论】:
是的,您需要编写自己的哈希函数。这并不像听起来那么糟糕:如果您的类有任何您知道将是合理唯一的可散列成员,您可以返回该成员的散列。
您可以通过专门化std::hash 或通过将哈希类作为模板参数显式传递来提供此哈希。
【讨论】: