C++STL中set的'insert'函数的原理是什么?



对于下面的这段代码:

int main()
{
std::set<Node> s;
for (int i = 0; i <= 5; i++)
s.insert(Node(i));
s.insert(Node(4));
for (auto itor = s.begin(); itor != s.end(); itor++)
{
std::cout << itor->val << ' ';
}
}

当符号"<"被覆盖时,如下所示,输出为:"5 4 3 2 1 0">

struct Node
{
int val;
Node(int _val = -1) : val(_val) {}
bool operator<(const Node &p) const
{
return val > p.val;
}
};

当我将函数更改为以下内容时:

bool operator<(const Node &p) const
{
return val >= p.val;
}

输出变为:"5 4 4 3 2 1 0"。 这种差异让我感到困惑,有人可以解释为什么会发生这种情况并解释"插入"功能的原理吗?

std::set默认对键类型使用operator<,因此在第一种情况下,它使用为Node定义的operator<来比较键,而又使用>来比较基础整数,因此您会看到整数的降序序列。

std::set期望提供的订单是作为先决条件的严格弱订单。 在第二种情况下,你的operator<不是一个严格的弱订单,因此你违反了前提条件,触发了未定义的行为。 因此,实现是混乱的。 (未定义的行为意味着任何事情都可能发生——程序可能会产生奇怪的结果、崩溃、让您的计算机着火、产生鼻魔等。

STL 容器中的自定义比较函数必须满足要求,即它们必须诱导出严格的弱排序关系。第二个运算符重载val >= p.val无法做到这一点,因此行为是未定义的。

从 cpp首选项 在 std::set 上:

在标准库使用比较要求的所有地方,唯一性都是通过使用等价关系来确定的。在不精确的术语中,如果两个对象 a 和 b 的比较都不比另一个少,则被认为是等价的:!comp(a, b) && !comp(b, a)

最新更新