C ++ STL中set的“插入”功能的原理是什么?

sin*_*ben 4 c++ stl set

对于下面的这段代码?

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 << ' ';
    }
}
Run Code Online (Sandbox Code Playgroud)

当符号'<'如下重写时,输出为:'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;
    }
};
Run Code Online (Sandbox Code Playgroud)

当我将函数更改为此:

bool operator<(const Node &p) const
{
    return val >= p.val;
}
Run Code Online (Sandbox Code Playgroud)

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

L. *_* F. 5

std::setoperator<默认情况下在键类型上使用,因此在第一种情况下,它使用operator<defined用于Node比较键,而键又用于>比较基础整数,因此您看到了一个由整数组成的降序序列。

std::set希望提供的订单是严格的弱订单作为前提。在第二种情况下,您operator<不是严格的弱命令,因此您违反了前提条件,从而触发了未定义的行为。因此,实现是混乱的。(未定义的行为表示可能发生任何事情,该程序可能会产生奇怪的结果,崩溃,使计算机着火,产生鼻恶魔等)


lub*_*bgr 5

STL容器中的自定义比较功能必须满足要求,即它们必须引起严格的弱排序关系。使用的第二个运算符重载val >= p.val无法完全做到这一点,因此行为未定义。

从std :: set上的cppreference

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