4

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

#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 得到了这个结果。但是,我使用 g++ 使用-std=c++0x( ideone link ) 以及同时使用and clang时获得了预期的输出。-std=c++0x-stdlib=libc++

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

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

4

3 回答 3

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 都有可能在内部重新分配向量。

于 2012-04-29T00:35:47.273 回答
5

由于对应的向量foo_it没有被修改

错误的。push_back破坏了对应的向量foo_it。销毁foo_it时失效 。foo[0]

于 2012-04-29T00:40:56.673 回答
0

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

于 2012-04-29T00:46:06.087 回答