std::set 的重载运算符<让我感到困惑
overloading operator < for std::set confused me
我知道我必须重载 std::set 的运算符<。
我用两个类重载运算符<:"UniqueID"和"UniqueIDWithBug"。唯一的区别是"UniqueID"在比较时添加了代码this->unique_id_a_ == t.unique_id_a_
。
然后我把相同的元素放到两个集合中。最后,我在集合中找到了一个元素。一套能找到,另一套找不到。这个问题让我困惑了很长时间。
struct UniqueID {
uint64_t unique_id_a_{0};
uint64_t unique_id_b_{0};
bool operator<(const UniqueID &t) const {
if (this->unique_id_a_ < t.unique_id_a_) {
return true;
}
if (this->unique_id_a_ == t.unique_id_a_ &&
this->unique_id_b_ < t.unique_id_b_) {
return true;
}
return false;
}
};
struct UniqueIDWithBug {
uint64_t unique_id_a_{0};
uint64_t unique_id_b_{0};
bool operator<(const UniqueIDWithBug &t) const {
if (this->unique_id_a_ < t.unique_id_a_) {
return true;
}
return (this->unique_id_b_ < t.unique_id_b_);
}
};
// init data
std::set<UniqueID> _set = {
{17303934402126834534u, 2922971136},
{8520106912500150839u, 3118989312},
{9527597377742531532u, 2171470080},
{10912468396223017462u, 3972792320},
};
std::set<UniqueIDWithBug> _set_with_bug = {
{17303934402126834534u, 2922971136},
{8520106912500150839u, 3118989312},
{9527597377742531532u, 2171470080},
{10912468396223017462u, 3972792320}};
UniqueID _unique_id = {10912468396223017462u, 3972792320};
UniqueIDWithBug _unique_id_with_bug = {10912468396223017462u, 3972792320};
if (_set.find(_unique_id) == _set.end()) {
std::cout << "_set not find" << std::endl;
}
if (_set_with_bug.find(_unique_id_with_bug) == _set_with_bug.end()) {
std::cout << "_set_with_bug not find" << std::endl;
}
输出:_set_with_bug找不到
您定义的用于std::set
(和其他(的小于运算必须是有效的严格弱排序。
您的 UniqueIDWithBug 排序不是。
例如,考虑:
UniqueIDWithBug a{1, 10};
UniqueIDWithBug b{2, 5};
现在观察a < b
和b < a
都是真的。这只是一个快速演示,表明您没有严格的弱排序;事实上,这根本不是命令!
因此,您的程序具有未定义的行为。std::set
机制的内部假定有效的排序,但你的不是。在这种情况下,可观察到的结果是"未找到元素"。它可能是"做披萨"。
构建一个好的严格弱排序可能很困难,但你已经完成了艰苦的工作,因为 UniqueID 的排序是正确的。
或者,完全放弃排序,定义哈希函数,并切换到 unordered_set
。
相关文章:
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 为什么我无法更改"set<set>"循环中的值<int>
- 对于set上的循环-获取next元素迭代器
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- 在声明中合并两个常量"std::set"(不是在运行时)
- 有没有办法对std::unordered_set、std::unrdered_map、std::set、std::map
- 将 std::set 与基于键的比较器一起使用
- 如何使用set实现无序数据结构?
- 使用运算符调用 void 函数时出错<set>
- 修改"std::set"中用户定义类型的值
- 生成提升::hana::set 的常量表达式问题
- 如何在构造函数参数中初始化"std::set"?
- 如何使用 lower_bound/upper_bound 从 std::set 获取索引号?
- 如何在 C++ 中转发声明 std::set?
- 重构使用动态强制转换的 std::set 的比较运算符
- set::find 查找不存在的元素
- 为什么 std::set.erase(first, last) 会影响从中获取 (first, last) 的容器?
- 是std :: set&lt; std :: future&gt;不可能存在