混淆使用c ++ STL迭代器

时间:2012-06-24 03:39:20

标签: c++ stl iterator

虽然我使用像这样的迭代器,

//include header files
using namespace std;

int main()
{
    map<int,int> intIntMap;
    map<int,int>::iterator pos;
    pos = intIntMap.begin();

    intIntMap[0] = 1;
    intIntMap[3] = 5;
    intIntMap[4] = 9;
    intIntMap[5] = 5;

    //遍历
    cout << (*pos).first << endl;

    while( pos != intIntMap.end() )
    {
        cout << pos->first << " <---> " << pos->second << endl;
        pos++;
    }

}

输出为4;

但是我使用像这样的迭代器:

//include header file
using namespace std;

int main()
{
    map<int,int> intIntMap;
    map<int,int>::iterator pos;

    intIntMap[0] = 1;
    intIntMap[3] = 5;
    intIntMap[4] = 9;
    intIntMap[5] = 5;

    //遍历
    pos = intIntMap.begin();
    cout << (*pos).first << endl;

    while( pos != intIntMap.end() )
    {
        cout << pos->first << " <---> " << pos->second << endl;
        pos++;
    }

}

输出是我想要的;

我想知道迭代器的使用之间有什么区别,当我插入新的键值对时,第一个迭代器会发生什么?谢谢!

addtion: 编译是使用gcc 4.1.2,感觉比较混乱,像这样:

compile is use gcc 4.1.2 , in feel more confused,like this :

5 个答案:

答案 0 :(得分:10)

由于在容器为空时调用了begin(),因此得到的迭代器等于end()(§23.1/ 7:“如果容器为空,则begin()== end ()“)。

将项目插入容器并没有改变这一点,因此您仍然拥有pos == intIntMap.end()

然后执行循环的零迭代,因为pos==end(),并且只在pos != end()执行循环。

在第二个示例中,您在插入数据后设置pos(),因此您获得了集合中的第一个项目,并迭代到最后一个项目。

编辑:就打印出地图的内容而言,我可能更喜欢这样做:

std::ostream &operator<<(std::ostream &os, std::pair<int, int> const &d) { 
    return os << d.first << " <---> " << d.second;
}

// ...

std::copy(intIntMap.begin(), intIntMap.end(), 
          std::ostream_iterator<std::pair<int, int> >(std::cout, "\n"));

答案 1 :(得分:2)

使用gdb进行此操作,我发现迭代器的first字段随着每次添加键值对而发生变化。似乎没有数据的地图的迭代器(由begin()返回)包含关于地图本身的一些元数据,特别是地图的大小(所述迭代器的first字段随着每个增长而增长添加键值对)。在添加单个键值对后调用begin()检索迭代器会导致“预期”行为。

答案 2 :(得分:-1)

迭代器旨在用于自迭代器实例化以来尚未修改的容器。第一个例子中的代码输出是未定义的,根据c ++标准(你仍然可以获得你想要的结果,你只是不能保证得到它,而且没有太多理由可以期待它。)

在第一种情况下迭代器没有发生任何事情,但是您打算引用它的容器已经发生了变化,并且不一定在内存中的同一位置。

答案 3 :(得分:-1)

容器修改使现有迭代器无效。

通常的做法是在使用之前获取迭代器,然后将其丢弃。您可以像这样使用for

#include <iostream>
#include <map>
using namespace std;

int main ()
{
  map<int, int> mymap;

  mymap[0] = 100;
  mymap[1] = 200;
  mymap[2] = 300;

  // show content:
  for (map<int, int>::iterator it = mymap.begin(); it != mymap.end(); it++)
    cout << (*it).first << " => " << (*it).second << endl;

  return 0;
}

答案 4 :(得分:-1)

简短回答:修改容器内容后,无法保证迭代器仍然有效。

由于此处的容器是map,通常实现为红黑树,因此在插入期间修改并重新平衡结构。

在第一个示例中,您将迭代器pos初始化为地图的开头。此时,迭代器对当前内容有效。但是一旦开始添加元素,迭代器就不再指向重组容器的新begin位置。

因此,第二个示例的工作原因是因为在完成对容器的所有修改后,您将迭代器设置为begin

通常,在迭代结构时修改结构是个坏主意。

这个问题有关于迭代器有效性的更多细节: