在类中存储Key Hash以提高效率

时间:2017-10-18 10:33:16

标签: c++ oop hash

我有一个类作为特定不可变信息X的容器,它是其对象的标识。此类还有一些额外的数据,但它们对对象的比较没有任何影响。如果a.X==b.X那就是它。这些对象保存在C ++中的unordered_mapunordered_set等哈希表中,并且在操作期间有大量的查找。并且定义的散列函数的一般方式 - 就我所观察到的 - 计算每次查找的散列(由于类的内容可能已经改变,因此通常是逻辑的)。

我的问题是:如果散列数据在对象的生命周期内保证是常量的。将_object_hash数据作为类的成员并提供仅仅比较a._object_hash==b._object_hash的哈希函数或者在C ++ std中是否存在任何回退这种方法是一种好习惯。容器或通常在OOP中。

1 个答案:

答案 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起)