C++ std::无序_设置中的KeyEqual是什么?

C++ std::无序_设置中的KeyEqual是什么?,c++,std,c++-standard-library,unordered-set,C++,Std,C++ Standard Library,Unordered Set,std::unordered_set中第三个参数KeyEqual的用途是什么?散列唯一性还不够吗 template< class Key, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>, class Allocator = std::allocator<Key> > class unordered_set; 模板< 类密钥, 类Ha

std::unordered_set
中第三个参数
KeyEqual
的用途是什么?散列唯一性还不够吗

template<
    class Key,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator<Key>
> class unordered_set;
模板<
类密钥,
类Hash=std::Hash,
类KeyEqual=std::等于,
类分配器=std::分配器
>类无序集;
对不起,如果这个问题听起来很幼稚。从Python /PHP迁移到C++:< /P>
现在我的
KeyEqual
实现总是重复
Hash
impl。所以我想知道我是否做得对。

但是如果我们有哈希冲突呢

图中演示了两个不同元素恰好具有相同的哈希值的情况。因此,在进行哈希运算时,哈希值可能不是唯一的


引用
std::无序集的

在内部,无序_集合中的元素不按任何顺序排序 特定顺序,但根据散列将其组织到桶中 允许用户直接快速访问单个图元的值 它们的值(平均时间复杂度不变)

因此,一个桶可以有多个元素!这两个元素将具有相同的哈希值,但不能保证其唯一性



唯一保证是独一无二的就是钥匙

很简单,集合需要知道两个键是否相等
KeyEqual
是执行此操作的机制


请记住,两个比较不相等的键可能散列为相同的值,集合需要能够检查该值。

不同的值不一定有不同的散列。例如,实际上有无限多个
std::string
对象,但是对于
std::hash()
的结果,只有2^N
std::size\t
对象,因此一些“哈希冲突”是不可避免的,尽管算法试图使它们不太可能发生


因此,
std::unordered_set
std::unordered_map
需要一种方法来测试元素是否相等,即使它们的散列值相等。

让我们举个例子,一组
int
和一个散列函数,它只执行一个简单的mod
%
操作

struct IntMod {
    constexpr std::size_t operator()(int i) const { return i % 10; }
};

std::unordered_set<int, IntMod> s;
如果我们添加一个只使用哈希函数的
KeyEqual
(就像您默认建议的那样),它会在第二次插入时中断

struct IntEq {
  constexpr bool operator()(int a, int b) const {
    return IntMod{}(a) == IntMod{}(b);
  }
};

std::unordered_set<int, IntMod, IntEq> s;
s.insert(25);  // hash == 5
s.insert(35);  // hash == 5
assert(*s.find(25) == 25);
assert(*s.find(35) == 35);  // now this fails. s.find(35) returns iterator to 25
struct IntEq{
constexpr bool运算符()(int a,int b)const{
返回IntMod{}(a)==IntMod{}(b);
}
};
std::无序的_集;
s、 插入(25);//散列==5
s、 插入(35);//散列==5
断言(*s.find(25)==25);
断言(*s.find(35)=35);//现在这失败了。s、 find(35)将迭代器返回到25

从未听说过哈希冲突?如果两个对象产生相同的散列,那么该相等谓词将用于确定它们是否比较相等。散列唯一性是否足够?如果您的密钥是
int
,而哈希函数是
[](int i){return i%10;}
,该怎么办?的文档有什么问题?来自前面注释的哈希冲突是原因N 1,但几乎所有stl容器都允许定制Comparison操作。如果您需要比较键的方法,或者您使用的键类型没有预先存在的Comparison运算符,那么应该替换它,如表[0]=“foo”替换table@mvidelgauz仅供参考,cplusplus.com有一些。用它来代替。我理解碰撞。但是如果我不关心碰撞呢?如果我想简单地说“我的哈希是100%唯一的”;如果我试图设置相同的元素,请给我异常或替换此元素?我想再问一个问题。。但是..是的@spajak这是另一个问题。容器不会在开箱即用的情况下为您这样做,因为它不是这样设计的。我的意思是它使用的哈希策略允许冲突,这就是为什么它需要
键来确定相等性。您必须创建自己的容器(将从
STL
one继承),并在需要时抛出异常。我编辑了你的问题,希望你不介意。:)<代码>s.插入(35)
应失效或更换旧元件。但我想到的可能不同于conatainer:)@spajak它只是认为
35
已经存在。你认为它应该如何“失败”?我说的失败是指throwin的误解
struct IntEq {
  constexpr bool operator()(int a, int b) const {
    return IntMod{}(a) == IntMod{}(b);
  }
};

std::unordered_set<int, IntMod, IntEq> s;
s.insert(25);  // hash == 5
s.insert(35);  // hash == 5
assert(*s.find(25) == 25);
assert(*s.find(35) == 35);  // now this fails. s.find(35) returns iterator to 25