C++\STL テスト用紙の 1 つにそのような質問があることに気付きました。
何か案は?
おそらく、コレクション内の要素を削除すると、ベクトル内の「すべて削除された後」のイテレータとセット内の削除されたイテレータのみが無効になるという事実と関係がありますか?
この違いは、イテレータ自体よりもコンテナの性質の違いに大きく関係しています。
1 つの側面は、これらのコンテナーの「並べ替え済み/並べ替えなし」の性質に関連しています。並べ替え済みコンテナー内にある要素は、順序が崩れるため、変更できません。
別の側面は、「コンパクト/拡張」格納メカニズムに関連しています。ベクトルの要素は単一の割り当てブロックにまとめて格納され、セット (またはリスト) の要素は個別に格納されます。その結果、ベクトルの挿入/削除により、要素の変位が変化します。セットまたはリストでの挿入/削除は再リンクを引き起こし、既存のすべての要素がその場所を保持します (したがって、それらを参照する反復子を無効にしません)
ストレージに常に関連するもう 1 つの側面は、vector::iterator が「ランダム アクセス」であることです。変位は算術的に計算できるため、++i、i+=3、i+=100 には同じ時間がかかります。セット (および「リンクされたコンテナー」) では、反復子は単に「双方向」です。++i と --i は即時計算ですが、i+=5 または i+=100 はまったく異なる時間がかかります (少なくとも線形ループが必要です)。
set::iterator
a が参照するオブジェクトは です。これconst
は、 a のエントリの値をset
順序どおりに変更することは許可されていないためです (値を変更すると、順序が崩れる可能性があります)。の場合はそうではありませんvector::iterator
。
例えば:
#include <vector>
#include <set>
int main()
{
std::set<int> s;
std::vector<int> v;
*v.begin() = 4;
*s.begin() = 4; // Line 10.
return 0;
}
MSVC++ コンパイラは次を出力します。
main.cpp(10): エラー C3892: 'std::_Tree<_Traits>::begin': const である変数に割り当てることはできません
g++ コンパイラは以下を出力します:
エラー: 読み取り専用の場所の割り当て 's.std::set<_Key, _Compare, _Alloc>::begin with _Key = int, _Compare = std::less, _Alloc = std::allocator.std::_Rb_tree_const_iterator<_Tp >::operator* with _Tp = int'</p>