为什么 unordered_set 的元素对于自定义 equal_to 不是唯一的

Mot*_*uda 2 c++ stl unordered-set

我试图更好地理解 unordered_set 。主要是,据我了解,unordered_set 中的元素在 equal_to 运算符之前应该是唯一的。因此,我决定通过一小段代码来测试一下

#include <iostream>
#include <unordered_set>
using namespace std;

struct m_int
{
    int x;
};
// template specialization for std::hash
template<>
struct std::hash<m_int>
{
std::size_t operator()(m_int const& x) const noexcept
{

return hash<int>{}(x.x); 
}
};
//template specialization for std::equal_to

template<>
struct std::equal_to<m_int>
{
bool operator()(const m_int &lhs, const m_int &rhs) const 
{
    
return abs(lhs.x-rhs.x)<=3;
}
};
int main() {
    unordered_set<m_int> m={{1},{2},{3},{4}};
    for(auto&x:m)
        cout<<x.x<<' ';
    cout<<endl;
    cout<<m.count({2})<<endl;
    // your code goes here
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我最初的想法是1会插入2,3会但会插入4。

我得到的输出是

4 3 2 1 
1
Run Code Online (Sandbox Code Playgroud)

因为根据我的 equal_to 1 和 2 是相同的,那么这个集合实际上包含重复,这违反了集合的定义。为什么会出现这种情况?我该如何解决这个问题?

Sam*_*hik 6

无序容器对其哈希和键相等函数有以下要求

如果根据 Pred 两个 Key 相等,则 Hash 必须为两个 Key 返回相同的值。

对于您的容器来说,情况并非如此。例如,1 和 4 比较相等,但它们(几乎肯定)具有不同的哈希值。这会导致未定义的行为。

这里还有另一个逻辑问题:1 等于 4,4 等于 7,但 1 不等于 7。这也无法计算。