1. ホーム
  2. c++

ベクターイレーズイテレータ

2023-10-02 16:34:16

質問

私はこのコードを持っています。

int main()
{
    vector<int> res;
    res.push_back(1);
    vector<int>::iterator it = res.begin();
    for( ; it != res.end(); it++)
    {
        it = res.erase(it);
        //if(it == res.end())
        //  return 0;
    }
}

"関数呼び出しによって消去された最後の要素に続く要素の新しい場所を指すランダムアクセスイテレータで、操作によってシーケンスの最後の要素が消去された場合はベクターエンドとなります。

このコードはクラッシュしますが、もし私が if(it == res.end()) の部分を使ってから戻ると、動作します。なぜでしょうか?forループがキャッシュしているのは res.end() をキャッシュしているので、not equal演算子が失敗するのでしょうか?

どのように解決するのですか?

res.erase(it) は常に次の有効なイテレータを返すので、もし最後の要素を消した場合は .end()

ループの最後には ++it が常に呼び出されるので、インクリメントして .end() をインクリメントすることになりますが、これは許されることではありません。

をチェックするだけで .end() をチェックするだけではバグが残ります。なぜなら、繰り返しのたびに必ず要素をスキップしてしまうからです ( it からの戻り値で 'インクリメント' されます。 .erase() からの戻り値、そしてループによって再び増加します)

のようなものが欲しいのではないでしょうか。

 while (it != res.end()) {
        it = res.erase(it);    
 }

で各要素を消去します。

(念のため。これは単純化された例だと仮定しています。もし、単にすべての要素に対して操作(例えば削除)を行わずに消したいのであれば、単純に res.clear() )

条件付きで要素だけを消す場合、おそらく次のようなものが必要でしょう。

for ( ; it != res.end(); ) {
  if (condition) {
    it = res.erase(it);
  } else {
    ++it;
  }
}