考虑一下:
// set_iterator.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <iostream>
#include <set>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
set<int> a1;
set<int> a2;
a1.insert(3);
a1.insert(4);
a1.insert(5);
a2.insert(1);
a2.insert(2);
a2.insert(6);
set<int>::iterator iter;
int x = 0;
for (iter = a1.begin(); iter != a1.end(); ++iter)
{
if (x == 0) {
x = 1;
a1.insert(a2.begin(), a2.end());
}
cout << *iter << endl;
}
system("pause");
return 0;
}
目标是访问集合中的每个元素一次。我认为在将元素插入a1后,迭代器无效。
输出是 3 4 5 6
1,2不打印。
我们如何编码这样的情况。
答案 0 :(得分:6)
实际上,迭代器 仍然有效。集合是基于节点的容器。
问题是在一个集合中,元素总是被排序。在插入之前,您的设置如下所示:
3 4 5
^
iter
插入后,您的设置如下所示:
1 2 3 4 5 6
^
iter
如果您希望能够做您正在做的事情,您将不得不使用不同的容器。
答案 1 :(得分:2)
我希望在遍历时它的大小增加时,访问该集合的每个元素一次。任何方式这样做? - iamrohitbanga 1小时前
在你的代码中,a1 = [3,4,5]。然后你得到一个指向a1开头的迭代器,它是'3'。然后将新元素插入a1,得到[1,2,3,4,5,6]。但是,你仍然指向相同的值,'3'。所以现在你继续迭代,你将打印3,4,5,6。
在获取迭代器后,为什么要插入列表仍然不清楚。为什么不能在迭代之前插入元素,就像@camh提到的那样?
如果您仍想这样做,请使用向量,因为这样可以将元素追加到列表的末尾,这意味着您仍将指向“3”,但列表现在将为[3] ,4,5,1,2,6],那些将按此顺序打印出来。
或者,添加:
for (iter = a1.begin(); iter != a1.end(); ++iter)
{
if (x == 0) {
x = 1;
a1.insert(a2.begin(), a2.end());
// Reset the iterator since we've modified the list
iter = a1.begin();
}
cout << *iter << endl;
}
这是丑陋的黑客代码,只能在这种特定情况下使用。更好的解决方案是@ camh's。如果你有某种原因你不能这样做,那么我们需要更多细节。
答案 2 :(得分:1)
问题不在于迭代器的有效性。
问题是set没有任何已定义的顺序(尽管在这种情况下,它选择了排序顺序,但我不相信STL的复杂性要求需要 - 另一个实现可能会选择另一个顺序)。
因此,在调用insert之后,任何迭代器仍然有效(因此您可以继续对指针进行deref并使其前进并保证仍然到达end())。但是插入的任何元素都可能在你的迭代器之前',除非你再次调用begin(),否则你将看不到它们。
答案 3 :(得分:0)
我们如何编码这样的情况。
您认识到“if(x == 0)”块中的代码只执行一次,并且该块中没有任何内容引用循环变量,因此应该移出循环。< / p>
a1.insert(a2.begin(), a2.end());
for (iter = a1.begin(); iter != a1.end(); ++iter)
{
cout << *iter << endl;
}
我不知道你的真实代码是否可以用类似的方式重构,但是关于插入后迭代器的有效性,this说:
Set具有重要的属性 将新元素插入集合中 不会使迭代器失效 指向现有元素。
因此,您的迭代器仍然有效,但您不一定能够假设所有插入的元素都将“在”当前位置之后,并且任何当前的前向迭代器都会到达它们。