反復子
反復子は、C++ 標準ライブラリ コンテナー内の要素を反復処理し、個々の要素へのアクセスを提供するオブジェクトです。 すべての C++ 標準ライブラリ コンテナーに反復子が用意されているため、アルゴリズムではその要素を格納するコンテナーの型を気にせずに標準的な方法で要素にアクセスできます。
メンバー関数、begin()
や end()
などのグローバル関数、前方または後方に移動するための ++
や --
といった演算子を使用して、反復子を明示的に使用できます。 また、range-for ループ (一部の反復子の種類の場合) や添字演算子 []
を使用することで、暗黙的に反復子を使用することもできます。
C++ 標準ライブラリでは、シーケンスまたは範囲の始まりが最初の要素になります。 シーケンスまたは範囲の終わりは、常に最後の要素の 1 つ後として定義されます。 グローバル関数の begin
および end
は、反復子を指定されたコンテナーに返します。 コンテナー内のすべての要素に対する通常の明示的な反復子のループは、次のようになります。
vector<int> vec{ 0,1,2,3,4 };
for (auto it = begin(vec); it != end(vec); it++)
{
// Access element using dereference operator
cout << *it << " ";
}
同じ処理を、range-for ループでより単純に実現できます。
for (auto num : vec)
{
// no dereference operator
cout << num << " ";
}
反復子には、5 つのカテゴリがあります。 これらのカテゴリを、機能が低い方から順に示します。
出力。 出力反復子
X
は++
演算子を使用してシーケンスを反復処理でき、*
演算子を使用して要素を 1 回だけ書き込むことができます。入力。 input 反復子
X
は++
演算子を使用してシーケンスを反復処理でき、*
演算子を使用して任意の回数だけ要素を読み取ることができます。==
と!=
演算子を使用することで、入力反復子を比較できます。 入力反復子のコピーを増分すると、その他のコピーのいずれも、安全に比較、逆参照、または増分できなくなります。転送。 前方反復子
X
は、 ++ 演算子を使用してシーケンスを反復処理でき、*
演算子を使用して任意の要素を読み取ったり、const 以外の要素を何度でも書き込んだりできます。 要素のメンバーにアクセスするには、->
演算子を使用します。前方反復子を比較するには、==
および!=
演算子を使用します。 前方反復子のコピーを複数作成して、それぞれを個別に逆参照または増分できます。 コンテナーへの参照を使用せずに初期化された前方反復子は、"NULL 前方反復子" と呼ばれます。 NULL 前方反復子を比較すると、常に等しくなります。双方向。 双方向反復子
X
は前方反復子の代わりに使用できます。 ただし、--X
、X--
、または(V = *X--)
のように、双方向反復子をデクリメントすることもできます。 要素のメンバーにアクセスし、前方反復子と同じ方法で双方向反復子を比較できます。ランダム アクセス。 random-access 反復子
X
は双方向反復子の代わりに使用できます。 ランダム アクセス反復子では、添字演算子[]
を使用して要素にアクセスできます。+
、-
、+=
、-=
演算子を使用して、指定された数の要素を前方または後方に移動したり、反復子間の距離を計算したりできます。 双方向反復子を比較するには、==
、!=
、<
、>
、<=
、>=
を使用します。
すべての反復子は、割り当てまたはコピーすることができます。 これらは軽量のオブジェクトであると見なされ、多くの場合、参照ではなく値によって、渡され、返されます。 前述のすべての操作は、有効な反復子に対して実行したときに例外をスローできないことに注意してください。
反復子のカテゴリの階層は、次の 3 つのシーケンスを表示することによって要約することができます。 シーケンスに対する書き込み専用アクセスの場合、次のいずれの反復子も使用できます。
出力反復子
-> 前方反復子
-> 双方向反復子
-> ランダム アクセス反復子
右矢印は、"後続の反復子で置き換え可能" であることを示します。出力反復子を必要とするすべてのアルゴリズムは前方反復子を使用してうまく動作しますが、その逆の方法ではうまく動作 "しません"。
シーケンスに対する読み取り専用アクセスの場合、次のいずれの反復子も使用できます。
入力反復子
-> 前方反復子
-> 双方向反復子
-> ランダム アクセス反復子
この場合、すべてのカテゴリのうちで最も弱いのは入力反復子です。
最後に、シーケンスに対する読み取り/書き込みアクセスの場合、次のいずれの反復子も使用できます。
前方反復子
-> 双方向反復子
-> ランダム アクセス反復子
オブジェクト ポインターは、常にランダム アクセス反復子としての機能を果たします。したがって、指定したシーケンスに対する適切な読み取り/書き込みアクセスをサポートしている場合は、反復子の任意のカテゴリとしての機能を果たします。
オブジェクト ポインター以外の反復子 Iterator
では、特殊化 iterator_traits<Iterator>
で必要なメンバーの型も定義する必要があります。 これらの要件は、パブリック基底クラス iterator から Iterator
を派生させて満たすことができます。
C++ 標準ライブラリのコンテナーとアルゴリズムで反復子がどのように使用されるかを知るには、各反復子カテゴリの約束ごとと制限事項を理解することが必要です。
Note
range-for ループを使用することにより、反復子の明示的な使用を避けることができます。 詳細については、「範囲ベースの for ステートメント」を参照してください。
Microsoft C++ では、コンテナーの境界を上書きしないようにするための、チェックを行う反復子とデバッグ反復子が提供されるようになりました。 詳細については、「チェックを行う反復子」および「デバッグ反復子のサポート」をご覧ください。