2016-02-15 10 views
6
ベクトルを考えると

vc, 1は用の範囲でベクトルを反復処理することができますベクトル上のイテレータの代わりにループの範囲を使用する必要がありますか?</p> <pre><code>for (auto c : vc) std::cout << c; </code></pre> <p>イテレータで:

for (auto it = vc.cbegin(); it != vc.cend(); ++it) 
    std::cout << *it; 

他の上に一つの方法を使用するための機能な理由があり、それともこれは単なるスタイルの問題ですか?

+4

範囲ベースのforループで 'auto'を使うとベクトル要素の* copy *が得られることに注意してください。オブジェクトのコピーが高価な場合は、望ましくないパフォーマンスの問題が生じる可能性があります。イテレータを使用すると、const参照が返されるので、コピーはここでは発生しません。範囲ベースのforのリファレンスを取得する方法は 'for(const auto&c:vc)... 'です。 –

答えて

4

パフォーマンスの観点からは、実際には違いはありません。 Bjarne Stroustrupが彼の本に書いているように、C++プログラミング言語第4版:

最も単純なループは、範囲の各要素 にプログラマがアクセスするだけです。

KISSの原理のファンとして、私はより複雑なものより単純な構造を好む傾向があります。しかし、それはあなたが達成したいことに本当に沸騰します。同じ本の中でBjarneは、range-forループが単純に設計されている理由を明らかにしています。

range-forループは意図的に単純な構造です。 の例では、これを使用すると同時に2つの要素に触れることはできず、 は2つの範囲を同時に効率的にトラバースできません。そのためには、一般的なfor-statement が必要です。

したがって、range-forループを使用できず、古典的なfor文に存在する必要があるというコンテキストがあります。

ボトムラインは、よりシンプルで読みやすいため、いつでも可能な限りrange-forループを使用します。

4

多かれ少なかれスタイルの問題ですが、このように考えてください。 range-forループは、明示的イテレータの使用法よりも簡潔です。あなたが書いたコードが少ないほど、物事が間違っている場所が少なくなります。

+1

また、ループの実装の詳細が隠されているので、読みやすくなります。 – emlai

+1

の範囲は、コンパイラにとってもより明確になり、最適化性が向上します。 – alcedine

+0

良い点。同意する。 – JesseTG

2

具体的な例として、それらは同等です。それらは同等であるため、当然のことながら、起こりにくい最短バージョンを好む傾向があります。

範囲-FORループも更に短縮することが提案された:varタイプauto&&(別名forwading /ユニバーサル参照)への参照を取るための最良の方法であるだろう

for (var : range) 

オブジェクト。ただauto varは安価ではないかもしれない各要素のコピーを作るでしょう。残念ながら、それは合格しませんでした。

通常、イテレータを直接操作することはできません。そのため、範囲を選択することをお勧めします。明示的イテレータは、範囲外の要素を指すこともあります。これは、範囲内を自由に移動できるため、未定義の動作につながります。

1

2つの例の間には2つの大きな違いがあります。まず、auto cは各要素のコピーを作成するので、不要なコピーを作成しない場合は、auto const& cを使用してください。第2に、範囲forは非constイテレータに関して実装されますが、forループはconstイテレータを使用します。これは問題ありません。vcが標準コンテナですが、内部共有ポインタを使ってコピーオンライトセマンティクスを実装するコンテナ(Qtのコンテナなど)があります。この場合、非constイテレータを使用するとコンテナ全体が不必要にコピーされます。あなたはこれを避けるため、まだC++ 17 std::as_constを使って素敵な範囲for構文を使用することができます。

for (auto const& c : std::as_const(vc)) 
    std::cout << c; 

ご使用の環境がそれを提供していない場合は、簡単にas_constの独自のバージョンを実装することができます。

関連する問題

 関連する問題