在学习数据结构,特别是哈希表时,我们被告知,向数据类型发明有效的哈希函数是一项非常艰巨的任务,但有人建议存在快速的快捷方式.也就是说,如果我们可以假设对象不在内存中移动,并且我们可以将对象相等定义为具有相同的内存地址(使用引用相等而不是值相等),那么我们可以获得对象的哈希码,如下所示:
#include<iostream>
template<typename T>
class hashcoder {
private:
union impl {
T* ptr;
int32_t hashcode; // or int64_t on a 64-bit architecture = architecture with 64-bit pointers
};
public:
static int32_t hash(const T& r) {
impl i;
i.ptr = &r;
return i.hashcode;
}
};
class myclass {
// whatever
};
int main() {
myclass m;
std::cout << hashcoder<myclass>::hash(m) << std::endl;
}
所以我的问题是:
>使用内存地址进行哈希码是否有任何问题(再次假设引用相等是所需的行为)?
>鉴于使用联合进行转换是undefined behaviour,我们如何将内存地址转换为整数?
>(请随意指出我在上面的代码中做出的任何其他错误.C指针很容易出错.)
解决方法:
>不,没有错;散列是一个整数,并保证每个对象都是唯一的,这样可以降低碰撞的概率.
>将指针强制转换为uintptr_t.不需要工会.此外,uintptr_t具有适合平台的大小,因此您不再需要使用int32_t等.
uintptr_t hash(const T &r)
{
return uintptr_t(&r);
}
(如果散列必须是32位,则将其转换为uint32_t,或者在64位平台上,使用appropriate magic组合两半.)