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

使用pair<int,int>作为unordered_map键是否需自定义哈希函数?

不能直接用std::pair<int,int>作为std::unordered_map的键(C++11及以上版本)

不行,哪怕编译器和标准库支持C11及更高版本,默认情况下也不能直接将std::pair<int, int>作为std::unordered_map的键。原因很明确:C标准库从未为std::pair模板提供过std::hash的特化版本,而std::unordered_map作为无序容器,要求键类型必须有对应的哈希函数(要么是默认的std::hash<Key>,要么是用户指定的自定义哈希器)。

你遇到的编译错误,正是因为标准库的静态断言检查发现找不到符合要求的哈希函数,直接触发了报错。

至于ChatGPT说这段代码可以运行,是它混淆了std::map和std::unordered_map的要求:std::map是有序容器,只需要键类型支持operator<(std::pair默认提供了这个运算符);但std::unordered_map必须同时满足两个条件:

  • 键类型支持operator==(std::pair默认满足)
  • 有对应的哈希函数(std::pair默认没有)

解决方案:自定义哈希函数

要让std::pair<int,int>作为std::unordered_map的键,你需要提供一个自定义哈希器,以下是两种常见实现方式:

方式1:定义自定义哈希结构体,声明时指定

#include <iostream>
#include <unordered_map>
#include <utility>
#include <functional>

// 自定义哈希结构体,采用boost风格的hash_combine实现,哈希分布更均匀
struct PairHash {
    template <typename T1, typename T2>
    std::size_t operator()(const std::pair<T1, T2>& p) const {
        std::size_t seed = 0;
        std::hash<T1> hasher1;
        std::hash<T2> hasher2;
        // 组合哈希值,避免简单异或导致的分布不均
        seed ^= hasher1(p.first) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        seed ^= hasher2(p.second) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
        return seed;
    }
};

int main() {
    // 声明unordered_map时,指定第三个模板参数为自定义哈希结构体
    std::unordered_map<std::pair<int, int>, int, PairHash> myMap;

    myMap[{1, 2}] = 10;
    myMap[{3, 4}] = 20;

    int value1 = myMap[{1, 2}];
    int value2 = myMap[{3, 4}];

    std::cout << value1 << " " << value2 << std::endl;

    return 0;
}

方式2:特化std::hash<std::pair<int,int>>(不推荐但可行)

你可以在std命名空间下特化std::hash,不过C++标准不鼓励对标准库模板进行非标准特化,仅在特定场景下使用:

#include <iostream>
#include <unordered_map>
#include <utility>
#include <functional>

namespace std {
    template<>
    struct hash<std::pair<int, int>> {
        size_t operator()(const std::pair<int, int>& p) const {
            size_t seed = 0;
            hash<int> hasher;
            seed ^= hasher(p.first) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
            seed ^= hasher(p.second) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
            return seed;
        }
    };
}

int main() {
    // 此时可直接使用,无需额外指定哈希器
    std::unordered_map<std::pair<int, int>, int> myMap;

    myMap[{1, 2}] = 10;
    myMap[{3, 4}] = 20;

    int value1 = myMap[{1, 2}];
    int value2 = myMap[{3, 4}];

    std::cout << value1 << " " << value2 << std::endl;

    return 0;
}

关键注意点

  • 哈希函数的核心是生成均匀分布的哈希值,避免碰撞,上面的hash_combine方式比简单的异或/加减更稳健
  • 从C11到最新的C23,标准库都没有为std::pair提供默认哈希,所以不管哪个版本都需要自定义哈希函数才能使用unordered_map

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 12:32:16