如本 链接 所述:
C 字符串没有专门化。 std::hash 产生指针值(内存地址)的哈希值,它不检查任何字符数组的内容。
这意味着使用相同的 char*
值,可以产生不同的哈希码。例如,有这个代码:
//MOK and MOV are template arguments
void emit(MOK key, MOV value) {
auto h = hash<MOK>()(key);
cout<<"key="<<key<<" h="<<h<<endl;
...
这是通过在同一个 key
(使用 MOK=char*
)值(但 4 个不同的标记/字符串对象)上调用 4 次 emit()
产生的输出:
key=hello h=140311481289184
key=hello h=140311414180320
key=hello h=140311414180326
key=hello h=140311481289190
如何获得 char*
的相同哈希码?我不想使用 boost
原文由 justHelloWorld 发布,翻译遵循 CC BY-SA 4.0 许可协议
当然,创建一个临时的
std::string
并对其进行散列是一种简单(且缓慢)的解决方案。如果您不想这样做,恐怕您将不得不实现自己的哈希函数。可悲的是,当前的 C++ 标准库没有提供脱离特定对象哈希解决方案的通用哈希算法。 (但有 一些希望 这可能会在未来改变。)假设你有一个函数
这将获取一个地址和一个大小,并返回一个根据该地址后面的那么多字节计算的哈希值。借助该功能,您可以轻松编写
然后将其专门用于您感兴趣的类型。
这让您只需要执行
hash_bytes
的练习。幸运的是,有一些相当不错的散列函数很容易实现。我的简单散列算法是 Fowler-Noll-Vo 散列函数。你可以用五行代码来实现它;请参阅链接的维基百科文章。如果您想花哨一点,请考虑以下实现。首先,我定义了一个通用的
template
可以专门用于任何版本的 FNV-1a 哈希函数。接下来,我为 32 位和 64 位版本提供别名。参数取自 Landon Curt Noll 的网站。
最后,我提供类型元函数来选择给定所需位数的算法版本。
有了这个,我们就可以开始了。
请注意此代码如何自动适应
std::size_t
为 32 或 64 位宽的平台。