【问题标题】:c++ hash<string> is there a way to get the same value in linux and windowsc++ hash<string> 有没有办法在linux和windows中获得相同的值
【发布时间】:2017-11-09 14:08:57
【问题描述】:

当我在 windows 和 linux 中散列给定字符串时,我试图找到一种方法来获得相同的结果。 但例如,如果我运行以下代码:

hash<string> h;
cout << h("hello");

它将在 windows 中返回 3305111549,在 linux 中返回 2762169579135187400。

如果不可能在这两个平台上获得相同的返回值,是否还有其他体面的哈希函数可以在两个系统上返回相同的值?

【问题讨论】:

  • "..有没有办法在 linux 和 windows 中获得相同的值'" - 是的,实现你自己的哈希函数。但这又有什么意义呢?如果你的哈希值在程序运行之间没有变化,你就提供了一个攻击面。
  • 哈希值可能会在程序执行之间发生变化。所以它在执行之间不可移植。
  • 如果你希望性能相同,为什么不写自己的哈希类?

标签: c++ hash


【解决方案1】:

没有。根据std::hash 参考,强调我的:

实际的哈希函数依赖于实现,而不是 要求满足除指定标准外的任何其他质量标准 以上。

更具体地说,您使用的是 std::hash<std::string> 模板特化,其哈希值:

等于相应 std::basic_string_view 类的哈希值

这也是依赖于实现的。所以不,你不能指望相同的std::hash 结果与不同的实现。此外,从 C++14 开始:

哈希函数只需要产生相同的结果 在一个程序的单次执行中输入相同的输入;

【讨论】:

    【解决方案2】:

    不仅您不能依赖不同平台之间的哈希值,而且该标准也不保证同一程序的不同运行之间的哈希值相同。它只保证在同一次运行期间该值是相同的。

    这是 C++14 标准对返回值提出的唯一要求(除了它的类型应该是 std::size_t)(17.6.3.4):

    返回的值应仅取决于参数k 程序的持续时间。 [注:因此所有的评价 具有相同 k 值的表达式 h(k) 对 a 产生相同的结果 给定程序的执行。 — 尾注] [ 注意:对于两个不同的值 t1 和 t2,h(t1) 和 > h(t2) 比较相等的概率应该很小,接近 1.0 / numeric_limits::max()。 ——尾注]

    (其中h 是哈希函子,k 是键)

    如果你想拥有相同的值,那么使用众所周知的哈希算法,比如MurmurHash3

    【讨论】:

      【解决方案3】:

      它不适用于std::hash

      实际的哈希函数是依赖于实现的,除了上面指定的那些之外,不需要满足任何其他质量标准。值得注意的是,一些实现使用将整数映射到自身的普通(身份)哈希函数。换句话说,这些散列函数旨在与无序关联容器一起使用,但不能用作加密散列。

      http://en.cppreference.com/w/cpp/utility/hash

      【讨论】:

        【解决方案4】:

        当我对给定的字符串进行哈希处理时,我试图找到一种方法来获得相同的结果 在 Windows 和 Linux 中。但例如,如果我运行以下代码:

        hash<string> h;
        cout << h("hello");
        

        它将在 windows 中返回 3305111549,在 linux 中返回 2762169579135187400。

        结果是正确的。正如其他答案中提到的,C++ 标准甚至不保证同一程序的不同执行之间的值相同。

        如果不能在这 2 个中获得相同的返回值 平台,是否有任何其他像样的哈希函数会返回 两个系统的值相同?

        是的!。您可能需要查看 Best hashing algorithms for speed and uniqueness 以获取要实现的良好哈希函数的列表。

        然而,在你选择了你想要使用的那个之后,你还需要一个额外的保证:两个平台之间的字符底层表示是相同的。也就是说,平台 1 中 'a' 的数值表示与平台 2 中的 'a' 相同。如果一个平台使用 ASCII,而另一个使用不同的编码方案,则不太可能得到相同的结果。


        同样,std::hash&lt;&gt; 已经拥有std::hash&lt;std::string&gt;专业化。因此,除了您的标准库的规定之外,您无法针对std::hash&lt;std::string&gt;()("hello") 的结果强制执行行为。您的选择是使用:

        • 自定义散列函数对象,例如myNAMESPACE::hash&lt;std::string&gt;()("hello"),或
        • 使用自定义字符串类型,并将其专门用于std::hash;例如std::hash&lt;MyString&gt;()("hello")

        【讨论】:

        • 非常感谢您,非常棒的东西。还有一个问题,当你提到'a'的数字表示时......只要代码是用c ++编写的,它不应该是ASCII吗?
        • @abass.mahdavi,不,it's not guaranteed to be ASCII。我相信今天有一些平台仍在使用 EBCDIC。但如今遇到这种不兼容 ASCII 的系统极为罕见。
        猜你喜欢
        • 2012-08-20
        • 2021-09-17
        • 1970-01-01
        • 2021-10-20
        • 2020-02-23
        • 2011-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多