1. ホーム
  2. c++

STLコンテナの終了イテレータと等しいイテレータをインクリメントするとどうなるか

2023-09-29 08:54:51

質問

イテレータがベクトルの最後の要素を指しているときに、イテレータを2つインクリメントするとどうなりますか? この質問 で、STLコンテナへのイテレータを2要素ずつ調整する方法を尋ねていますが、2つの異なるアプローチが提供されています。

  • 算術演算子の形式を使用する - +=2 または ++ を 2 回使用する。
  • またはstd::advance()を使用する

イテレータがSTLコンテナの最後の要素以降を指す場合のエッジケースについて、VC++ 7で両方テストしてみました。

vector<int> vec;
vec.push_back( 1 );
vec.push_back( 2 );

vector<int>::iterator it = vec.begin();
advance( it, 2 );
bool isAtEnd = it == vec.end(); // true
it++; // or advance( it, 1 ); - doesn't matter
isAtEnd = it == vec.end(); //false
it = vec.begin();
advance( it, 3 );
isAtEnd = it == vec.end(); // false

vectorや他のコンテナをトラバースする際に、vector::end()と比較するようにというアドバイスを何度か見かけたことがあります。

for( vector<int>::iterator it = vec.begin(); it != vec.end(); it++ ) {
    //manipulate the element through the iterator here
}

イテレータがループ内の最後の要素を越えて進めば、for-loop文の比較はfalseと評価され、ループは楽しく未定義の動作を続けることになることは明らかです。

もし、イテレータで advance() または何らかのインクリメント操作を使用して、コンテナの終わりを越えてポイントさせるなら、私はこの状況を検出することができないということは正しいですか? もしそうなら、ベスト プラクティスは何ですか - そのようなアドバンスメントを使用しないことですか?

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

以下は、ニコライ・ヨスッティ氏の著書からの引用です。

advance()は を越えるかどうかをチェックしないことに注意してください。 を越えるかどうかをチェックしないことに注意してください (チェックできないのは イテレータは一般に コンテナを知らないため、チェックできません)。 したがって、この関数を呼び出すと を呼び出すと、未定義の動作になることがあります。 演算子 ++ をシーケンスの終端に対して呼び出すことは は定義されていません。

つまり、イテレータを範囲内に維持する責任は、完全に呼び出し側にあるのです。