[解決済み] イテレータループとインデックスループの比較【重複あり
質問
重複の可能性があります。
なぜ配列のインデックスではなくイテレータを使用するのですか?
C++の知識を復習しているところ、イテレータに行き当たりました。私が知りたいことの一つは、それらを特別なものにして、私はなぜこれが知りたいです。
using namespace std;
vector<int> myIntVector;
vector<int>::iterator myIntVectorIterator;
// Add some elements to myIntVector
myIntVector.push_back(1);
myIntVector.push_back(4);
myIntVector.push_back(8);
for(myIntVectorIterator = myIntVector.begin();
myIntVectorIterator != myIntVector.end();
myIntVectorIterator++)
{
cout<<*myIntVectorIterator<<" ";
//Should output 1 4 8
}
はこれよりマシです。
using namespace std;
vector<int> myIntVector;
// Add some elements to myIntVector
myIntVector.push_back(1);
myIntVector.push_back(4);
myIntVector.push_back(8);
for(int y=0; y<myIntVector.size(); y++)
{
cout<<myIntVector[y]<<" ";
//Should output 1 4 8
}
そして、std 名前空間を使うべきでないことも知っています。この例はcprogrammingのウェブサイトから持ってきただけです。では、なぜ後者の方が悪いのか、教えていただけませんか?何が大きく違うのでしょうか?
どのように解決するのですか?
イテレータの特別な点は、イテレータが
アルゴリズムとコンテナ
. 一般的なコードでは、STLアルゴリズムを組み合わせて使うことをお勧めします。
find
,
sort
,
remove
,
copy
) などのデータ構造に対して、思い描いた計算を実行する (
vector
,
list
,
map
など) を作成し、そのアルゴリズムとイテレータをコンテナに供給します。
あなたの特別な例では、このような組み合わせで書くことができます。
for_each
アルゴリズムと
vector
コンテナ (以下のオプション 3) を参照) を使用することもできますが、これは std::vector を反復処理する4つの異なる方法のうちの1つでしかないのです。
1) インデックスに基づく反復処理
for (std::size_t i = 0; i != v.size(); ++i) {
// access element as v[i]
// any code including continue, break, return
}
メリット
: C スタイルのコードに慣れた人なら誰でも知っている、異なるストライドを使ってループさせることができる (例.
i += 2
).
デメリット
シーケンシャル・ランダム・アクセス・コンテナ (
vector
,
array
,
deque
の場合、動作しません。
list
,
forward_list
または連想コンテナです。また、ループの制御は少し冗長です(init, check, increment)。C++の0ベースインデックスを意識する必要がある。
2) イテレータを用いた反復処理
for (auto it = v.begin(); it != v.end(); ++it) {
// if the current index is needed:
auto i = std::distance(v.begin(), it);
// access element as *it
// any code including continue, break, return
}
メリット
: より汎用的で、すべてのコンテナ (新しい順不同の連想コンテナも含む) で動作します。また、異なるストライド (たとえば
std::advance(it, 2)
);
デメリット 現在の要素のインデックスを取得するために余分な作業が必要になる (list や forward_list では O(N) になる可能性がある).ループ制御がやや冗長(init, check, increment)。
3) STL for_each アルゴリズム + ラムダ
std::for_each(v.begin(), v.end(), [](T const& elem) {
// if the current index is needed:
auto i = &elem - &v[0];
// cannot continue, break or return out of the loop
});
メリット 2)と同様、ループ制御の削減(チェック&インクリメントなし)、バグ率の低減(初期化、チェック&インクリメント、オフバイワンエラー)、など。
デメリット
明示的なイテレータループと同じですが、ループ内のフロー制御の可能性が制限されます (continue, break, return が使用できません)。
operator++
).
4) 範囲指定ループ
for (auto& elem: v) {
// if the current index is needed:
auto i = &elem - &v[0];
// any code including continue, break, return
}
メリット 非常にコンパクトなループ制御、現在の要素への直接アクセス。
デメリット インデックスを取得するための余分なステートメントがある。異なるストライドを使用することができない。
何を使うか?
を反復処理する特定の例では
std::vector
もし本当にインデックスが必要なら(例えば前の要素や次の要素にアクセスしたり、ループ内でインデックスを表示したりログに残したり)、あるいは1以外のストライドが必要なら、明示的なインデックスループを、それ以外なら range-for ループを使うでしょう。
一般的なコンテナ上の一般的なアルゴリズムの場合、ループ内のフロー制御がなく、ストライド1が必要なコードでなければ、明示的なイテレータ・ループを使いますが、その場合はSTL
for_each
+ ラムダ
関連
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み] for'ループでインデックスにアクセスする?
-
[解決済み] リスト内のアイテムのインデックスを検索する
-
[解決済み] JavaScriptのオブジェクトをループスルーまたは列挙するにはどうすればよいですか?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] インデックスを指定してリストから要素を削除する方法
-
[解決済み] オブジェクトをメンバーとして、プレーンなJavaScriptオブジェクトをループさせる方法
-
[解決済み] クラスター化インデックスと非クラスター化インデックスの実際の意味は何ですか?
-
[解決済み] C++コンテナにおけるイテレータの無効化ルール
-
[解決済み] std::vectorのイテレータのインデックスを取得する最も効果的な方法は何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】構造体のベクター初期化について
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】Visual C++で "Debug Assertion failed "の原因となる行を見つける。
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】Enterキーを押して続行する
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み】配列のインデックスの代わりにイテレータを使用する理由は?