在c++中使用set时,我编写了以下代码:它将元素从1推到50分为两个集合s1和s2,然后在这两个集合中从相同的值迭代到打印值直到固定的极限。但是我无法理解为什么我为s1和s2获得不同的输出,因为唯一的区别是s1.erase(it ++)被写为{s2.erase(it); it ++;}。

#include<bits/stdc++.h>
using namespace std;
set<int> s1,s2;
int main()
{
    int l,r,i;
    for(i=1;i<=50;i++)
    {       s1.insert(i);
            s2.insert(i);
    }
    //scanf("%d%d",&l,&r);
    l=3;r=9;

    printf("Output 1:\n");
    set<int>::iterator it=s1.lower_bound(l);

    while(it!=s1.end() && (*it<=r))
    {
            printf("Before deletion: %d\n",*it);
            s1.erase(it++);
            printf("After deletion: %d\n",*it);
    }

    it=s2.lower_bound(l);
    printf("Output 2\n");
    while(it!=s2.end() && (*it<=r))
    {
            printf("Before deletion: %d\n",*it);
            s2.erase(it);
            it++;
            printf("After deletion: %d\n",*it);
    }
    return 0;
  }

输出为:
 Output 1:
Before deletion: 3
After deletion: 4
Before deletion: 4
After deletion: 5
Before deletion: 5
After deletion: 6
Before deletion: 6
After deletion: 7
Before deletion: 7
After deletion: 8
Before deletion: 8
After deletion: 9
Before deletion: 9
After deletion: 10
Output 2
Before deletion: 3
After deletion: 2
Before deletion: 2
After deletion: 4
Before deletion: 4
After deletion: 6
Before deletion: 6
After deletion: 7
Before deletion: 7
After deletion: 5
Before deletion: 5
After deletion: 8
Before deletion: 8
After deletion: 10

最佳答案

s2.erase(it);
it++;

简单。这是非法的。一旦在该节点上添加了erase,就不允许使用迭代器,甚至不能对其进行递增。您有Undefined Behaviour

未定义行为是令人讨厌的事情。您的代码可能会崩溃,做一些奇怪的事情,甚至看起来可以正常工作。最后一种情况是最糟糕的,因为它可能会在将来的某个未知时刻崩溃。

尽管语言本身没有定义细节,但是实际原因是将其实现为二叉树(红黑树),因此每个节点都包含指向其左,右子级以及可能是其父级的指针。这些指针用于在树中移动。一旦删除了节点,检查这些指针就不可能指望它正常工作。

在另一种情况下:s1.erase(it++);在对其进行erase编码之前先增加迭代器的数量,这样您就可以快乐地继续查看容器的其余部分。

另一个可能是it = s2.erase(it);,因为erase返回下一个迭代器(请注意,这可能是end())。这是一个更常见/惯用的模式,仅出于这个原因应该被首选,但是对于其他容器类型也很有效(您的版本不是)。

对于不同类型的容器,迭代器失效规则是不同的,因此请确保小心read the documentation。 (请注意,这并不是真正的官方文档,只有标准文档,但是此网站非常受欢迎)。

我还建议您包括实际使用的standard headers(例如<set>)和avoid using namespace std;

关于c++ - 以几乎相同的方式使用C++ STL中的set的删除属性后获得不同的输出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42953328/

10-12 05:34