C++ 使用带嵌套向量的迭代器时出现意外行为

C++ 使用带嵌套向量的迭代器时出现意外行为,c++,vector,iterator,c++11,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&

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

#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;
}
作为参考,我使用g++版本4.2和4.6以及Clang3.1得到了这个结果。但是,我使用
-std=c++0x
()使用g++获得了预期的输出,并且在同时使用
-std=c++0x
-stdlib=libc++
时也使用了
clang

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


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

push_
使迭代器无效,就这么简单

std::vector<int>::iterator foo_it = foo[0].begin();
foo.push_back(std::vector<int>(3, 2));
std::vector::迭代器foo_it=foo[0]。begin();
foo.push_-back(std::vector(3,2));
在此之后,
foo_ti
不再有效。任何插入/推回都有可能在内部重新分配向量

由于与
foo\u相对应的向量,因此未对其进行修改


错。
push_-back
破坏了与
foo_-it
对应的向量
foo\u当
foo[0]
被销毁时,它变得无效。

我猜错误的理解是,向量>是指针向量,当重新分配外部向量时,指向内部向量的指针仍然有效,这对**int是正确的。但是,重新分配向量也会重新分配所有内部向量,这也会使内部迭代器无效。

并且也会使指向向量元素的任何指针或引用无效,例如通过
操作符[]
获得的指针或引用。他没有在
向量上调用
push_back
,他从中获得迭代器。@LuchianGrigore调用
foo[0]。begin()
,然后在
foo
push_back
,而不是
foo[0]
@SethCarnegie:允许外部向量的
push_back
复制其内部元素,并且复制的向量的迭代器与源向量的迭代器不匹配。(然后,在外部向量重新分配后,原始向量被破坏,它使迭代器无效)它工作在<> > STD= C++ +0x因为内部向量是移动而不是复制的。@ DavidBrown:考虑STD::vector是可以的,如果C++ 11承认任何其他行为,情况就不可能了。(因为您不能复制unique_ptr s)不总是真的。(事实上,在C++11中总是假的)我通过打印出两个值的地址来测试这一点,它们是相同的。这意味着来自内部向量的数据已被重新分配,对吗?这取决于您所说的地址。不过,在C++11中,
std::vector
必须将其向内移动(而不是复制)如果可能,移动操作不会使迭代器无效或导致重新分配。@比利-什么?如果对象被移动到新位置,那么对原始对象的迭代器现在肯定无效。@Bo:迭代器只指向移动的项。(以向量为例,move操作将内存指针从一个向量对象移动到另一个向量对象,但迭代器是指向该内存块的指针——而该块根本没有被移动修改)
std::vector<int>::iterator foo_it = foo[0].begin();
foo.push_back(std::vector<int>(3, 2));