c++ - unordered_set 中可能有两个键,它们被认为是相等的?

标签 c++ hash unordered-set

From here :

Pred: The unordered_set object uses this expression to determine whether two element keys are equivalent. No two elements in an unordered_set container can have keys that yield true using this predicate.

还有来自 23.5.6.1/1 的:

An unordered_set is an unordered associative container that supports unique keys (an unordered_set contains at most one of each key value) and in which the elements’ keys are the elements themselves. The unordered_set class supports forward iterators.

但是如果我定义我自己的哈希器和使用类类型的不同特性的等效操作,我可以绕过这个。

#include <iostream>
#include <unordered_set> //for unordered_set and unordered_multiset

using namespace std;

struct A{
    A() = default;
    A(int a, int b): x(a), y(b) {}
    int x = 0, y = 0;

};

size_t hasher(const A &sd){
    return hash<int>()(sd.x);
}

bool eqOp(const A &lhs, const A &rhs){
    return lhs.y == rhs.y;
}


int main(){

    unordered_set<A, decltype(hasher)*, decltype(eqOp)*> unorderedA(10, hasher, eqOp);

    unorderedA.emplace(2,3);
    unorderedA.emplace(3,3);

    for(const auto& c : unorderedA)
        cout << c.x << " " << c.y << endl;
}

输出;

3 3
2 3

我明白发生了什么:哈希器根据它们的 x 值将每个键放在不同的桶中。然而,由于它们的 y 值,我的 eqOp 函数应该认为这两个键是相等的,但由于它们被放置在不同的存储桶中,因此永远不会检查它们是否相等。那么一个无序的容器可以包含两个等价的key只要进入不同的bucket是不是正常的功能。还是编码员有责任确保编写哈希器和谓词以将等效键放在同一个桶中?或者我的 eqOp 函数是否违反了编译器未检测到的规则?

在集合和映射中很明显:提供给它们的谓词定义了严格的弱排序,因此两个被认为等价的键只有一个元素与之关联。在无序映射中,我不太清楚:两个等效的键可以有不同的元素与之关联,只要这些键位于不同的桶中。但是上面的那些消息来源感觉他们告诉我的不是这样。

最佳答案

不,这是不可能的。您的示例无效,因为标准要求您为等效键返回相同的哈希值:

23.2.5 Unordered associative containers

  1. Two values k1 and k2 of type Key are considered equivalent if the container’s key_equal function object returns true when passed those values. If k1 and k2 are equivalent, the hash function shall return the same value for both. [ Note: Thus, when an unordered associative container is instantiated with a non-default Pred parameter it usually needs a non-default Hash parameter as well. — end note ]

图书馆用户无论如何都无法确保值落入不同的桶中,因为没有定义所有可能的哈希值如何整体映射到桶索引或映射上的操作如何改变桶的数量。

关于c++ - unordered_set 中可能有两个键,它们被认为是相等的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31772406/

相关文章:

c++ - 使用 hash_map 时,在 STL 字符串上使用的最佳散列算法是什么?

c++ - 在 C++ 中使用函数作为类成员

将 gcrypt MD5 输出与现有哈希进行比较

c++ - 如何在 C++ 中更有效地生成这么多排列?

c++ - "factory"方法是正确的模式吗?

C++ 由作用域引起的对象的条件存储分配

c++ - OpenCV 3.4:CPU和CUDA中调整大小的结果在C++中不匹配

c++ - 将成员函数指针传递到模板中

c++ - 使用自定义散列函数插入 unordered_set

c++ - Unordered_set迭代器随机