在C+中使用set的erase属性后获得不同的输出+;STL以几乎相同的方式 在C++中使用set时,我编写了以下代码,它只把元素从1到50推到两个集合S1和S2,在这两个集合之后,我从相同的值迭代到打印值,直到固定的限制。但我无法理解为什么s1和s2的输出不同,因为唯一的区别是s1.erase(it++)被写为{s2.erase(it);it++;}
简单。这是违法的。一旦删除了该节点,就不允许使用迭代器,甚至不能增加迭代器。你有 不明确的行为是令人讨厌的事情。您的代码可能会崩溃,做一些奇怪的事情,甚至看起来工作正常。最后一个案例是最糟糕的,因为它可能在未来的某个未知点破裂 尽管语言本身没有定义细节,但实际的原因是它是作为二叉树(红黑树)实现的,因此每个节点都包含指向其左、右子节点的指针,可能还有指向其父节点的指针。这些指针用于在树中移动。一旦节点被删除,当您检查这些指针时,就不可能期望它工作 在另一种情况下:在C+中使用set的erase属性后获得不同的输出+;STL以几乎相同的方式 在C++中使用set时,我编写了以下代码,它只把元素从1到50推到两个集合S1和S2,在这两个集合之后,我从相同的值迭代到打印值,直到固定的限制。但我无法理解为什么s1和s2的输出不同,因为唯一的区别是s1.erase(it++)被写为{s2.erase(it);it++;},c++,stl,set,C++,Stl,Set,简单。这是违法的。一旦删除了该节点,就不允许使用迭代器,甚至不能增加迭代器。你有 不明确的行为是令人讨厌的事情。您的代码可能会崩溃,做一些奇怪的事情,甚至看起来工作正常。最后一个案例是最糟糕的,因为它可能在未来的某个未知点破裂 尽管语言本身没有定义细节,但实际的原因是它是作为二叉树(红黑树)实现的,因此每个节点都包含指向其左、右子节点的指针,可能还有指向其父节点的指针。这些指针用于在树中移动。一旦节点被删除,当您检查这些指针时,就不可能期望它工作 在另一种情况下:s1.擦除(it++)在删除迭代
s1.擦除(it++)
在删除迭代器之前,先递增迭代器,这样就可以愉快地继续查看容器的其余部分
另一种可能是it=s2。擦除(it)
,因为erase
返回下一个迭代器(注意这可能是end()
)。这是一种更常见的/惯用的模式,仅出于这个原因应该优先考虑,但它也适用于其他容器类型(您的版本不适用)
对于不同类型的容器,迭代器无效规则是不同的,因此请确保仔细阅读。(请注意,这不是真正的官方文档,只有标准,但该网站非常受欢迎)
我还建议您包括您实际使用的文件(例如,
),以及。#include
——而不是指定标准的include头。请看一看,使用Visual Studio 2015(调试)运行您的代码时,代码在@BobTFish给出的答案指出的行崩溃。因此“输出”甚至没有达到您所显示的程度(这就是未定义行为的全部内容)。旁注:不过,请注意,这适用于集合/映射/列表,但不适用于向量,在向量中,所有指向被删除元素的迭代器都会失效!它应该是it=s2。擦除(it)代码>请添加一个指向文档的链接:@Raxvan Ha,你比我快-只是想将此添加到我之前的评论中…it=s2.erase(它)代码>是惯用的。答案中应大力提倡这一点。
#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++;