在使用c++中的set时,我编写了以下code.It,只将元素从1推入到50,然后将元素推入s1和s2两个集合,然后从相同的值迭代到打印值,直到有固定的限制。但是,我无法理解为什么要为s1和s2获得不同的输出,因为惟一的区别是s1。擦除(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发布于 2017-03-22 13:41:01
s2.erase(it);
it++;很简单。这是违法的。一旦有了erased节点,就不允许使用迭代器,甚至不允许增加迭代器。你有https://en.wikipedia.org/wiki/Undefined_behavior。
不明确的行为是一件讨厌的事情。您的代码可能崩溃,做一些奇怪的事情,甚至看起来正常工作。最后一种情况是最糟糕的,因为它可能会在未来某个未知的时刻破裂。
尽管语言本身并没有定义细节,但实际的原因是这是作为二叉树(红色-黑色树)实现的,因此每个节点都包含指向其左、右子节点的指针,并且可能包含它的父节点。这些指针用于在树中移动。一旦节点被删除,您就不可能期望它在检查这些指针时工作。
在另一种情况下:s1.erase(it++);在迭代器运行erase之前增加迭代器,这样您就可以愉快地继续查看容器的其余部分。
另一种可能是it = s2.erase(it);,因为erase返回下一个迭代器(注意,这可能是end())。这是一种更常见/惯用的模式,仅出于这个原因,它就应该是首选的模式,但它也适用于其他容器类型(您的版本不适用)。
迭代器失效规则对于不同类型的容器是不同的,因此请确保仔细地使用阅读文件。(请注意,这不是真正的正式文档,只有标准,但这个网站非常受欢迎)。
我还建议您包括实际使用的标准标头 (例如<set>)和using namespace std;。
https://stackoverflow.com/questions/42953328
复制相似问题