可能性のある複製:
配列インデックスの代わりに反復子を使用する理由
string::iterator it;
for (it = str.begin(); it < str.end(); it++)
cout << *it;
cout << endl;
何故なの:
for (int i = 0; i < str.size(); i++)
cout << str[i];
cout << endl;
String :: iteratorも範囲チェックを提供していないようです。インデックスではなくstring::iterator
を使用する必要があるのはなぜですか?
ありがとう。
インデックスは、ランダムアクセスをサポートするコンテナ(特定の位置への直接アクセス)にのみ使用できます。
イテレータは、コレクション/データ構造にアクセスする統一された方法を提供します。コードをリファクタリングする際の柔軟性は計り知れません。
イテレーターは標準インターフェースです。イテレータを使用すると、異なるアルゴリズムで同じアルゴリズムを使用できます。それらを使用するかどうかの最終決定は、使いやすさと読みやすさに基づいてあなた次第です。
たとえば、標準変換アルゴリズムを使用して、std::string
を大文字に変換します。
std::string str = "A String";
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
str
は"A STRING"
と等しくなります。
具体的にはstd :: stringについては、ランダムアクセスをサポートし、その方法がより簡単なので、インデックスを使用することをお勧めします。反復子を使用することが「推奨」される唯一の理由は、反復子がシーケンスにアクセスするための標準インターフェースを提供するためです。
重複:
とはいえ、それは汎用性の問題です。配列アクセスよりもSTLを使用するイテレータの方がlotより多くのことができます。また、コードをリファクタリングし、文字列をベクター、リスト、または ロープ に変更する必要がある場合、コードをまったく書き直す必要はありません。
最後に、反復における安全性の問題があります。ループにNEXT文字inをアクセスしたい場合、イテレータを使用すると安全に実行できますが、配列の添え字を増やすと最後の要素でセグメンテーション違反が発生する可能性があるため、別のチェックが必要です。
述べられているように この質問では 、size()メソッドはO(1)であるとは限りません
反復しているクラスがわからない場合(テンプレート引数であるため)、反復子を使用する必要があります。反復子を提供するすべてのクラスが[]
を提供するわけではないためです[]
を提供し、O(1)時間)で機能するものを提供します。したがって、イテレータを使用することで、関数ができるだけ多くのクラスで機能することを確認します(ただし、 C配列ではありません)。
この特定のケースでは、個人的な好みや多分時期尚早な最適化を除いて、どちらか一方を好む理由はありません。
両方とも機能します。
主な理由は一貫性です。イテレータをリクエストして先に進めることで、同じ方法でコレクションまたは文字列の文字を繰り返し処理します。
++it
の実装の詳細が、ポインター演算を含むstr[i]
と比較してポインターの増分をもたらすことは、言及する価値があるとは言いません。また、範囲チェックも実装の詳細です。
イテレータはより安全で、他の誰かが投稿したように柔軟性を提供します。さらに、インデックスは、(効率的に)ランダムアクセス(つまり、特定の位置の要素への直接アクセス)をサポートするコンテナに対してのみ使用できます。イテレータはより一般的な概念です。イテレータは、リンクされたリスト、ファイル、および他の多くのデータ構造の効率的な走査を提供します。多くの場合、より効率的なコードの生成につながります。
イテレータがインデックスよりも優先されるべきもう1つの理由は、すべてのコレクションが一定時間のランダムアクセスをサポートしているわけではないことです。
たとえば、リンクリストのn-番目の要素が必要な場合は、取得するまですべての先行要素(インデックス0 ..n-1)を走査する必要がありますn-th要素に。 (この操作には線形時間がかかります。)
(シーケンシャル)イテレータは、コレクション内の位置を記憶し、次の要素が必要なときに常に最初からやり直す必要はありません。この例では、文字列内の文字にランダムな順序で実際にアクセスする必要はありませんが、順番にアクセスする必要があるため、イテレータを使用するとほぼ確実に高速になります(一定時間)。