You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

32位环境下返回uint64_t的函数为何能作为unordered_map哈希器?

32位Visual Studio 2022下unordered_map接受返回uint64_t的哈希器的原因解析

问题场景

在32位环境下使用Visual Studio 2022编译以下C++代码:

#include <iostream>
#include <unordered_map>
#include <iterator>

using namespace std;
class point
{
public:
    float x, y;
    point() = default;
    point(float _x, float _y)
    {
        x = _x, y = _y;
    }
};
struct hash_point
{
    uint64_t operator()(const point& p) const
    {
        return uint64_t(p.x) + uint64_t(p.y);
    }
};

bool operator==(const point& p, const point& q)
{
    return p.x == q.x && p.y == q.y;
}
int main()
{
    point p = { 3.0f,3.0f };
    unordered_map<point, int, hash_point> m;
    cout << "size " << sizeof(size_t) << endl;
    cout << "size " << sizeof(m.hash_function()(p)) << endl;
    return 0;
}

运行后输出:

size 4 //I'm running this code under 32bits .
size 8 // strange ,hasher is supposed to return size_t type .

疑问:根据文档,哈希器需返回size_t类型,但编写的hash_point返回uint64_t类型,为何能作为unordered_map的哈希器使用,且返回值大小为8?

解答

  1. C++标准对哈希器的实际要求
    C++标准并未强制要求哈希器必须严格返回size_t类型,只要求哈希函数的返回值是无符号整数类型,并且可以隐式转换为size_t。uint64_t属于无符号整数类型,满足这个转换要求,因此编译器允许它作为unordered_map的哈希器返回类型,不会触发编译错误。

  2. 返回值大小为8的原因
    你直接调用m.hash_function()(p)时,得到的是hash_point中operator()返回的uint64_t类型值,所以sizeof结果为8。而unordered_map内部会自动将这个uint64_t值隐式转换为size_t(32位环境下是4字节)后使用,转换过程会截断高位数据,但这属于合法的隐式转换。

  3. 潜在问题与建议
    虽然这种写法可以通过编译,但不推荐使用:32位环境下将64位哈希值截断为32位,会丢失高位信息,可能导致哈希碰撞概率上升,影响unordered_map的性能。正确的做法是让哈希器直接返回size_t类型,或者显式将uint64_t转换为size_t后返回,比如:

struct hash_point
{
    size_t operator()(const point& p) const
    {
        return static_cast<size_t>(uint64_t(p.x) + uint64_t(p.y));
    }
};

内容的提问来源于stack exchange,提问作者iouvxz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:13:25