【问题标题】:What are the principles of the 'insert' function of set in C++ STL?C++ STL中set的'insert'函数的原理是什么?
【发布时间】:2019-08-30 07:02:15
【问题描述】:

下面这段代码:

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 << ' ';
    }
}

当符号'

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'。 这种差异让我感到困惑,有人可以解释为什么会发生这种情况并解释“插入”函数的原理吗?

【问题讨论】:

标签: c++ stl set


【解决方案1】:

std::set 默认在 key 类型上使用 operator&lt;,所以在第一种情况下,它使用为 Node 定义的 operator&lt; 来比较 key,然后使用 &gt; 来比较底层整数,因此您会看到整数的降序。

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

【讨论】:

    【解决方案2】:

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

    来自cppreference std::set:

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

    【讨论】:

    • 感谢您的回答,我已经弄清楚了。
    猜你喜欢
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 2017-09-19
    • 2012-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-16
    相关资源
    最近更新 更多