c++怎么自定义哈希函数用于unordered_map_c++ unordered_map自定义哈希函数教程


在C++中使用自定义类型作为unordered_map的键时,需提供哈希函数和相等比较。1. 可通过定义仿函数或lambda实现哈希函数;2. 结构体需重载operator==;3. 哈希设计应减少冲突,推荐组合标准哈希并引入扰动。

在 C++ 中使用 unordered_map 时,如果键的类型不是内置类型(如 int、string),就需要自定义哈希函数。这是因为 unordered_map 内部依赖哈希表实现,需要一个能将键转换为哈希值的函数。

1. 自定义哈希函数的基本方式

可以通过两种常见方式为 unordered_map 提供自定义哈希函数:

  • 定义一个函数对象(仿函数)
  • 使用 lambda(需配合构造函数传参)

下面以自定义结构体为例说明。

2. 示例:用结构体作为 key

假设我们有一个表示二维点的结构体 Point,想把它作为 unordered_map 的键:

#include 
#include 

struct Point {
    int x, y;
    Point(int x, int y) : x(x), y(y) {}
    
    // 为了让 unordered_map 正常工作,还需要定义 operator==
    bool operator==(const Point& other) const {
        return x == other.x && y == other.y;
    }
};

// 自定义哈希函数对象
struct HashFunction {
    size_t operator()(const Point& p) const {
        // 简单哈希:将 x 和 y 混合
        return std::hash{}(p.x) ^ (std::hash{}(p.y) << 1);
    }
};

然后就可以这样使用:

std::unordered_map pointMap;
pointMap[Point(1, 2)] = "origin";
pointMap[Point(3, 4)] = "target";

for (const auto& [key, value] : pointMap) {
    std::cout << "(" << key.x << ", " << key.y << "): " << value << "\n";
}

3. 使用 Lambda 表达式(局部定义)

如果你只想在某个作用域内使用自定义哈希,可以用 lambda,但注意不能直接作为模板参数(lambda 类型无法命名),需要借助其他手段,比如:

auto hash = [](const Point& p) {
    return std::hash{}(p.x) ^ (std::hash{}(p.y) << 1);
};

// 需要同时提供相等比较
auto equal = [](const Point& a, const Point& b) {
    return a.x == b.x && a.y == b.y;
};

std::unordered_map map(8, hash, equal);

注意这里必须指定初始桶数(如 8)、哈希函数和等于函数,否则会报错。

4. 哈希函数设计建议

  • 尽量让不同输入产生不同的哈希值,减少冲突
  • 可以组合标准类型的哈希,例如使用 std::hash
  • 避免简单异或,尤其是对称字段(如 x 和 y 互换后哈希相同),可加入位移或乘法扰动
  • 推荐写法(更健壮):
size_t operator()(const Point& p) const {
    size_t h1 = std::hash{}(p.x);
    size_t h2 = std::hash{}(p.y);
    return h1 ^ (h2 << 1 | h2 >> (sizeof(size_t)*8-1)); // 引入旋转扰动
}

或者使用官方推荐的哈希组合方法(C++ 标准未提供,但可手动实现):

template
void hash_combine(size_t& seed, const T& v) {
    seed ^= std::hash{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}

size_t operator()(const Point& p) const {
    size_t seed = 0;
    hash_combine(seed, p.x);
    hash_combine(seed, p.y);
    return seed;
}

这种方式能有效降低哈希碰撞概率。

基本上就这些。只要提供哈希函数和相等比较,并重载 operator== 或指定 equals 函数,就能让任意类型作为 unordered_map 的键。


# c++  # ios  # stream  # 作用域  # red  # String  # 构造函数  # 结构体  # int  # Lambda  # operator  # 对象  # 自定义  # 如果你  # 尤其是  # 两种  # 可以用  # 可以通过  # 能让  # 只想  # 还需要  # 为例 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: php错误怎么开启_display_errors与log_errors的设置【汇总】  Mac电脑如何恢复出厂设置_Mac抹掉数据并重装系统【安全指南】  Windows 11无法安全删除U盘提示设备正在使用中怎么办_Windows 11找出占用设备进程  Win11时间怎么同步到原子钟 Win11高精度时间同步设置【指南】  MySQL 中使用 IF 和 CASE 实现查询字段的条件映射  如何用列表一次性对 DataFrame 的指定列应用字典映射  Win11开机自检怎么关闭_跳过Win11开机磁盘扫描修复方法【技巧】  php修改数据怎么改富文本_update更新html内容注意事项【说明】  Python性能剖析高级教程_cProfileLineProfiler优化案例解析  c++怎么使用std::tuple存储多元组数据_c++ 11获取元素与解包操作【技巧】  Win11怎么关闭系统声音_Win11系统提示音静音设置【详解】  如何使用Golang搭建本地API测试环境_快速验证接口功能  c++ nullptr与NULL区别_c++11空指针规范  如何使用Golang实现路由参数绑定_使用Mux和Request解析路径变量  C++如何解析JSON数据?(nlohmann/json库示例)  Win11无法安装软件怎么办_Win11解除应用安装限制设置【修复】  Win11怎样激活系统密钥_Win11系统密钥激活步骤【攻略】  Python路径拼接规范_跨平台处理说明【指导】  Win11怎么设置系统还原_Windows11系统属性保护设置  Mac的访达(Finder)怎么用_Mac文件管理入门教程【详解】  LINUX怎么查看进程_LINUX ps命令查看运行服务  Win11怎么设置虚拟内存_Windows 11优化内存性能提升速度【技巧】  C++中的Pimpl idiom是什么,有什么好处?(隐藏实现)  如何使用Golang指针与结构体结合_修改结构体内部字段  Win11怎么卸载Photos应用_Win11卸载Photos应用方法【教程】  c++ reinterpret_cast怎么用 c++最危险的类型转换【详解】  Go 中的 := 运算符:类型推导机制与使用边界详解  c++的static关键字有什么用 静态变量和静态函数的应用场景【教程】  Python解释执行模型_字节码流程说明【指导】  mac怎么分屏_MAC双屏显示与分屏操作技巧【指南】  如何在JavaScript中动态拼接PHP的base_url与jQuery变量  Linux怎么禁止Root用户远程登录_Linux系统SSH加固与安全设置【教程】  如何在 Go 结构体中正确初始化 map 字段  如何使用Golang包导出规则_控制函数和变量可见性  Win11麦克风没声音怎么设置_Win11麦克风权限及驱动修复【教程】  Win11如何隐藏桌面图标 Win11一键隐藏/显示桌面图标【指南】  全球各国上班时间表外贸邮件时间  C#如何在一个XML文件中查找并替换文本内容  如何使用Golang实现负载均衡_分发请求到多个服务节点  Win11应用商店下载慢怎么办 Win11更改DNS提速下载【修复】  如何在 Python 测试中动态配置 @backoff 装饰器的重试次数  如何在Golang中使用log包输出不同级别日志_Golang log日志管理与分类  php485返回空数组怎么回事_php485数据接收为空排查指南【详解】  微信里的php文件怎么变mp4_微信接收php转mp4操作步骤【操作】  C++中引用和指针有什么区别?(代码说明)  Python生成器表达式内存优化_惰性计算说明【指导】  C++如何获取CPU核心数?(std::thread::hardware_concurrency)  Windows10如何查看保存的WiFi密码_Win10命令行netsh wlan查询  Mac怎么开启“任何来源”_Mac安装未签名应用的设置方法【解决】  Win11怎么设置默认PDF阅读器 Win11修改PDF打开方式【步骤】 

 2025-11-15

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.