for
イテレータは、ループなどで配列インデックスを使用する場合と同様に、標準ライブラリコンテナの要素を「循環」させるためによく使用されます。
イテレータは多くの理由で無効になる可能性があります。for
これが発生する一般的なケースの1つは、次のようなループを使用する場合です。
std::deque<int> c;
for(std::deque<int>::iterator i = c.begin(); i != c.end(); ++i) {
// do some stuff to the deque's elements here
}
上記のループの最後で、イテレータは、両端キューの最後の実際の要素の1ブロック後i
の「要素」を指します。あなたが次のようなことをしようとした場合
*i = 88;
上記のループの終了直後は、コンテナがメモリを「ポイント」しfor
ていないため、問題になります。i
しかし、マイヤーズが話している可能性が高いのは、標準では、両端キューの実装の多くが設計者に公開されているということです。Dequeは通常、複数の要素を保持するメモリブロックのリンクリストとして実装されるため、ベクトルとは異なり、要素がメモリ内で互いに隣接するという保証はありません。さらに、イテレータには、これらの「ブロック」に関する情報が含まれている必要があります。これにより、イテレータはスムーズにトラバースできます(つまり、イテレータは単なるポインタではありません)。
たとえばpush_back()
、新しい要素であるが、メモリの「最後の」チャンクにスペースがない場合、dequeは、新しい要素(および最後に追加される将来の要素)に新しいメモリブロックを割り当てる必要があります。以前使用していたイテレータは、この新しいメモリチャンクを「認識」していない可能性があるため、無効である可能性があります。
一方、参照と実際のポインタは、このコンテキストでは、コンテナ内の個々のオブジェクトを参照/参照するために使用されます。私が書いたら
int& j = *c.begin();
その場合、jはの最初の要素への参照ですc
。私がそうしたら
c.push_front(74);
j
両端キューの先頭にない場合でも、前の最初の要素を参照します。
ただし、両端キューの途中に何かを挿入すると、それらの連続するメモリのチャンクの1つを効果的に分割し、そこに新しい要素を絞り込もうとしている可能性があります。スペースを確保するには、一方または他方の要素をメモリ内でシャッフルする必要があります(場合によっては新しいメモリを割り当てる必要があります)。これは必然的に、挿入のその「側」にある要素へのポインタ/参照を無効にします。挿入された要素のためにどの程度正確にスペースを空けるかは実装者次第であるため、挿入に関してどこにあるかに関係なく、すべてのベットはポインター/参照に関してオフになります。