为什么我不能在std::unordered_map<std::pair<int,int>, int>中使用operator[],但是可以在相同键值对的std::map中使用呢?

6
#include <bits/stdc++.h>

std::unordered_map<std::pair<int,int>, int> mp;

int main()
{
    mp[make_pair(1, 2)]++;
}

在使用[]运算符时,我得到了这个结果。
error: no match for ‘operator[]’ (operand types are ‘std::unordered_map<std::pair<int, int>, int>’ and ‘std::pair<int, int>’)

然而,当使用std::map时,没有错误发生。为什么?

我该如何让它与std::unorderd_m一起正常工作?


你正在使用哪个版本的C++? - prisar
我尝试在G++11和G++17上编译,结果相同。 - Kavaliro
1个回答

4
当使用std::map时不会出现错误,为什么?如何使其在std::unorderd_map中工作?因为它们是不同的。在std::unorderd_map中,元素是根据其键的哈希值放置的。
template<
    class Key,
    class T,
    class Hash = std::hash<Key>,  
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator< std::pair<const Key, T> >
> class unordered_map;

相反,std::map只需要一个比较函数就能对键进行排序。

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >
> class map;

你的 std::map<std::pair<int,int>, int> 被编译通过的原因是,std::pair 定义了 operator< 用于对键排序,而 std::map 使用它来排序其键,然而,对于 std::pair 的哈希函数未被定义,因此 std::unorderd_map 需要定义一个哈希函数来保持元素在其桶中。你需要自己定义一个哈希函数。
例如,你可以按照以下方式定义一个自定义哈希函数:
#include <unordered_map>
#include <cstddef>
#include <functional>

struct CustomHash
{
  template <typename T, typename U>
  std::size_t operator()(const std::pair<T, U> &x) const
  {
    return std::hash<T>()(x.first) ^ std::hash<U>()(x.second);
  }
};

int main()
{
    std::unordered_map<std::pair<int,int>, int, CustomHash> mp;
    mp[std::make_pair(1, 2)]++;
    return 0;
}

PS: #include <bits/stdc++.h>是一种不好的编码习惯。为什么呢?请看这里


2
如果使用模板,我建议有两个模板参数,这样您可以计算std::pair<int, double>或类似类型的哈希值... - Aconcagua
1
@Aconcagua 确实。让我用那个编辑一下。然而,OP只有 int,这意味着根本不需要模板。 - JeJo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接