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 )、および とclangの両方-std=c++0xを 使用すると、期待される出力が得られ-stdlib=libc++ます。

ここで何らかの未定義の動作を呼び出したことがありますか? もしそうなら、これは現在定義されている動作 C++ 11 ですか? それとも、これは単にコンパイラ/標準ライブラリのバグですか?

編集C++03 では、ベクトルの要素が再割り当て時にコピーされるため、反復子が無効になっていることがわかります。ただし、これがC++ 11で有効かどうかを知りたいです(つまり、ベクトルの要素はコピーではなく移動されることが保証されており、ベクトルを移動してもイテレータは無効になりません)。

4

3 に答える 3

5

に対応するベクトルfoo_itは変更されていないため、

違う。にpush_back対応するベクトルを破壊しましたfoo_itfoo_itが破棄された時点で無効になりました foo[0]

于 2012-04-29T00:40:56.673 に答える
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 に答える
0

vector< vector < int > > はポインターのベクトルであり、外側のポインターが再割り当てされても、内側のポインターへのポインターは引き続き有効であり、これは **int に当てはまります。ただし、代わりに、ベクトルを再割り当てすると、すべての内部ベクトルも再割り当てされるため、内部反復子も無効になります。

于 2012-04-29T00:46:06.087 に答える