使用嵌套向量的迭代器的意外行为

时间:2012-04-29 00:32:46

标签: c++ vector iterator c++11

此示例程序获取另一个向量中包含的向量元素的迭代器。我将另一个元素添加到包含向量,然后打印出以前获得的迭代器的值:

#include <vector>
#include <iostream>

int main(int argc, char const *argv[])
{
    std::vector<std::vector<int> > foo(3, std::vector<int>(3, 1));
    std::vector<int>::iterator foo_it = foo[0].begin();
    std::cout << "*foo_it: " << *foo_it << std::endl;
    foo.push_back(std::vector<int>(3, 2));
    std::cout << "*foo_it: " << *foo_it << std::endl;
    return 0;
}

由于未修改向foo_it的向量,我希望迭代器仍然有效。但是,当我运行此代码时,我得到以下输出(也在ideone上):

*foo_it: 1
*foo_it: 0

作为参考,我使用g ++版本4.2和4.6以及clang 3.1获得此结果。但是,当使用-std=c++0xclang时,我使用-std=c++0xideone link)和-stdlib=libc++获得g ++的预期输出。

我在这里以某种方式调用了一些未定义的行为吗?如果是这样,现在定义的行为C ++ 11?或者这只是一个编译器/标准库错误?

编辑我现在可以看到,在C ++ 03中,迭代器无效,因为在重新分配时复制了向量的元素。但是我仍然想知道这在C ++ 11中是否有效(即向量的元素保证被移动而不是复制,并且移动向量不会使它的迭代器无效)。

3 个答案:

答案 0 :(得分:5)

push_back使迭代器失效,就像那样简单。

std::vector<int>::iterator foo_it = foo[0].begin();
foo.push_back(std::vector<int>(3, 2));

在此之后,foo_ti不再有效。任何insert / push_back都有可能在内部重新分配向量。

答案 1 :(得分:5)

  

由于未对foo_it的矢量进行修改

错误。 push_back销毁了与foo_it对应的向量。 <{1}}被销毁后foo_it无效。

答案 2 :(得分:0)

我猜错误的感觉是那个矢量&lt;矢量&lt; int&gt; &GT;是指针的向量,当外部指针被重新分配时,指向内部的指针仍然有效,这对于** int是正确的。但是,重新分配向量也会重新分配所有内部向量,这使得内部迭代器也无效。