我有一个 C 字符串 ( wchar_t const*
),其生命周期由其他数据结构拥有;对字符串的引用通过指针传递。我想将这些实例放入unordered_map
. 是否有一个标准工具我可以用来获取这个哈希而不构建临时std::wstring
和调用std::hash<std::wstring>
?
请注意,它std::hash<T*>
返回指针的哈希值,而不是该指针指向的字节流内容的哈希值。
我有一个 C 字符串 ( wchar_t const*
),其生命周期由其他数据结构拥有;对字符串的引用通过指针传递。我想将这些实例放入unordered_map
. 是否有一个标准工具我可以用来获取这个哈希而不构建临时std::wstring
和调用std::hash<std::wstring>
?
请注意,它std::hash<T*>
返回指针的哈希值,而不是该指针指向的字节流内容的哈希值。
正如您所指出的,并且正如这里std::hash
所解释的, C 风格的字符串没有专门化。从链接页面引用:
C 字符串没有专门化。
std::hash<const char *>
生成指针值(内存地址)的哈希值,它不检查任何字符数组的内容。
std::hash
因此,应用于任何此类字符串时产生的哈希值与其实际内容无关,因此不适合您需要的目的。
你能做什么?构造一个临时对象是不可行的,因为它可能涉及分配,这会引入异常不安全,并且总是一个无用的副本。正如user657267在上面的评论中指出的那样,如果你的标准库支持basic_string_view
,它还应该提供相应的专业化,在这个页面std::hash
中列出。
最后,您可以推出自己的散列算法。如果哈希值将用于无序容器中,算法的质量将影响性能,但不会影响键的唯一性(即不会有任何冲突;您可以测试它),正如我之前发现的那样。这个例子实现了 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
符。如果数据存储在其他地方,它无论如何都不会有用。
编辑:我刚刚意识到我提出的示例算法适用于窄字符串。我想你仍然可以搜索一个对宽字符进行操作的。