我有一个类作为特定不可变信息X的容器,它是其对象的标识。此类还有一些额外的数据,但它们对对象的比较没有任何影响。如果a.X==b.X
那就是它。这些对象保存在C ++中的unordered_map
或unordered_set
等哈希表中,并且在操作期间有大量的查找。并且定义的散列函数的一般方式 - 就我所观察到的 - 计算每次查找的散列(由于类的内容可能已经改变,因此通常是逻辑的)。
我的问题是:如果散列数据在对象的生命周期内保证是常量的。将_object_hash
数据作为类的成员并提供仅仅比较a._object_hash==b._object_hash
的哈希函数或者在C ++ std中是否存在任何回退这种方法是一种好习惯。容器或通常在OOP中。
答案 0 :(得分:1)
您的方法很好,提供:
如果operator==(a, b)
则保证a.hash_code() == b.hash_code()
在将对象序列化到磁盘,网络或其他任何地方时,不保存hash_code。
如果加载/反序列化对象,则重新计算哈希值
对于程序的任何一次运行,std :: hash(x)保证为每次调用不可变x返回相同的值。但是,无法保证同一程序的后续运行会产生相同的结果。
因此,防止预先计算的哈希码的序列化/反序列化非常重要。
您可能需要考虑包装器
template<class T>
struct hashed: T
{
hashed(T&& t)
: T(std::move(t))
, hash_code_(std::hash<T>()(*this)) {}
std::size_t hash_code() const
{
return hash_code_;
}
private:
std::size_t hash_code_;
};
namespace std {
template<class T>
struct hash<hashed<T>>
{
auto operator()(hashed<T> const& t) const {
return t.hash_code();
}
}
}
参考:http://en.cppreference.com/w/cpp/utility/hash
特别注意:
只需要在程序的单次执行中为相同的输入产生相同的结果;这允许盐渍哈希防止碰撞DoS攻击。 (自c ++ 14起)