是否有标准机制来检索C字符串的哈希值?

时间:2014-07-24 00:35:28

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

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

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

1 个答案:

答案 0 :(得分:0)

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

  

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

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

你能做什么?构建一个临时工具是不可能的,因为它可能涉及一个分配,这将引入异常不安全,并且永远是一个无用的副本。正如上面评论中指出的user657267,如果您的标准库支持basic_string_view,它还应提供this page中列出的相应std::hash专精。

最后,你可以推出自己的哈希算法。如果哈希值将在无序容器中使用,算法的质量将影响性能,但不影响密钥的唯一性(即不会有任何冲突;您可以测试它),因为我发现{{3 }}。这个例子实现了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说明符。如果数据存储在其他地方,它无论如何都不会有用。

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