イテレータ破壊
イテレータの使い回しには注意が必要です。要素追加によってメモリの再確保や要素の再配置が行われるためです。イテレータ取得後に要素の再配置が行われると、元のイテレータは無効な物となるため注意が必要です。この現象は俗に「イテレータ破壊」と呼ばれています。
std::vector<int> v = {2};
auto i = v.begin();
v.insert(i, 0); // v == {0, 2}
++i;
v.insert(i, 1); // v == {0, 0, 2}
// 期待していた結果: v == {0, 1, 2}
このように、有効期限切れのイテレータへの参照値は不定なものとなります。
イテレータ破壊はpush_back関数やpush_front関数による要素追加処理やresize関数、erase関数による要素削除処理によっても引き起こされます。
対処方法
insert関数の戻り値を元のイテレータ変数に再代入することで、正しい挿入処理が可能になります。
std::vector<int> v = {2};
auto i = v.begin();
i = v.insert(i, 0); // v == {0, 2}
++i;
i = v.insert(i, 1); // v == {0, 1, 2}
insert関数は要素再配置後の正しいイテレータを返しますので、その値で古いイテレータを上書きすれば、常に新鮮で正確なイテレータを扱うことが可能になります。
なおpush_backやresize関数による要素操作時には、begin関数やend関数でイテレータを再取得する必要があります。