【问题标题】:Is there a standard mechanism to retrieve the hash of a C string?是否有标准机制来检索 C 字符串的哈希?
【发布时间】:2014-09-15 09:26:22
【问题描述】:

我有一个 C 字符串 (wchar_t const*),它的生命周期由其他数据结构拥有;对字符串的引用通过指针传递。我想将此类实例放入unordered_map。有没有一个标准工具可以用来获取这个哈希值,而无需构造一个临时的std::wstring 并调用std::hash<std::wstring>?

请注意,std::hash<T*> 返回指针的哈希值,而不是该指针指向的字节流内容的哈希值。

【问题讨论】:

  • 如果您的库支持它,您可以使用库基础 TS 中的 std::experimental::string_view,它还为 string_views 添加哈希。
  • “有没有……?”不,您可以在每个字符上使用std::hash<wchar_t>,并结合boost::hash_combine 或类似名称(例如here),我相信您知道... ;-)。有一些针对 C++14 的散列相关提案会有所帮助,同时没有 void*,size_t 变体很疯狂,但这就是它的大小。

标签: c++ hash unordered-map unordered-set


【解决方案1】:

正如您所指出的,正如 here 所解释的,C 风格的字符串没有 std::hash 特化。引用自链接页面:

C 字符串没有特化。 std::hash<const char *> 产生指针值(内存地址)的哈希值,它 不检查任何字符数组的内容。

因此,std::hash 产生的哈希值在应用于任何此类字符串时与其实际内容不相关,因此不适合您需要的用途。

你能做什么?构造一个临时对象是不可行的,因为它可能涉及分配,这会引入异常不安全,并且总是一个无用的副本。正如user657267在上面的评论中指出的那样,如果你的标准库支持basic_string_view,它还应该提供相应的std::hash特化,列在this page中。

最后,您可以推出自己的哈希算法。如果哈希值将用于无序容器中,算法的质量将影响性能,但不会影响键的唯一性(即不会有任何冲突;您可以测试它),正如我发现的earlier .这个例子实现了对我有用的 X65599 算法:

#include <cstring>

struct
    hasher final
{
    constexpr std::size_t
        operator()
        ( const char * const s )
        const noexcept
        {
            std::size_t h = 0;

            for ( std::size_t i = 0 , l = std::strlen(s) ; i < l ; ++i )
            {
                h += h * 65599 + s[i];
            }

            return h ^ (h >> 16);
        }
};

如果您的编译器不支持 C++14,您可以删除 constexpr 说明符。如果数据存储在其他地方,它无论如何也不会有用。

编辑:我刚刚意识到我提出的示例算法适用于窄字符串。我想你仍然可以搜索一个对宽字符进行操作的。

【讨论】:

    猜你喜欢
    • 2019-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    • 2011-10-19
    • 1970-01-01
    • 2013-05-28
    • 2011-04-27
    相关资源
    最近更新 更多