在插入新元素时,我们如何遍历集合的所有元素?

时间:2009-10-10 04:38:13

标签: c++ stl

考虑一下:

// 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不打印。

我们如何编码这样的情况。

4 个答案:

答案 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具有重要的属性   将新元素插入集合中   不会使迭代器失效   指向现有元素。

因此,您的迭代器仍然有效,但您不一定能够假设所有插入的元素都将“在”当前位置之后,并且任何当前的前向迭代器都会到达它们。