web-dev-qa-db-ja.com

C ++ 11範囲ベースのforループ効率「const auto&i」と「auto i」

C++ 11では、次のようにコンテナを反復処理できます。

for(auto i : vec){
   std::cout << i << std::endl;
}

しかし、私はこれが不必要に-不必要にであることを知っています、なぜなら私はprintvecの値---([〜#〜] edit [〜#〜]:の各要素)vecのコピーを作成するため、代わりに行う:

for(auto &i : vec){
   std::cout << i << std::endl;
}

しかし、私はvecの値が決して変更されず、const-correctnessを順守することを確認したいので、次のことができます。

for(const auto &i : vec){
   std::cout << i << std::endl;
}

だから私の質問は次のとおりです:コンテナの値を見るだけでlookが必要な場合、最後のループではありません(const auto &i)([〜#〜] edit [〜#〜]:の各要素)vec?の余分なコピーを持たないことにより効率が向上するため、常に優先されます。

私は開発中のプログラムを持っています。このプログラムでは効率が非常に重要であるため(最初にC++を使用する理由)、全体を通してこの変更を検討しています。

53
user2052561

はい。引数を読み取るだけの場合と同じ理由で、パラメータconst&を作成します。

T        // I'm copying this
T&       // I'm modifying this
const T& // I'm reading this

これらは「デフォルト」です。ただし、Tが基本型(ビルトイン)の場合、コピーはエイリアスよりも安価であるため、通常は読み取り用にconst T(参照なし)に戻ります。


効率が非常に重要であるため、全体を通してこの変更を行うことを検討しているプログラムを開発しています

  1. ブラインドスイープの変更を行わないでください。動作中のプログラムは、高速だが壊れたプログラムよりも優れています。
  2. ループをどのように反復するかは、おそらく大きな違いにはなりません。あなたは理由のためにループしていますよね?ループの本体が犯人である可能性が高くなります。
  3. 効率が重要な場合は、推測ではなく(プロファイラーを使用して、プログラムのどの部分が実際に遅いかを見つけます。 mightが遅い部分推測が間違っている理由については、#2を参照してください。
68
GManNickG

ベクトルに文字列が含まれていると想像してください。長い文字列。 5000の長い文字列。それらを不必要にコピーすると、ひどく非効率的なforループがうまく書かれてしまいます。

コードが意図に従っていることを確認してください。ループ内でコピーが必要ない場合は、コピーを作成しないでください。

上記のように参照&を使用するか、反復子を使用します。

1
Visiedo

免責事項:一般に、autoauto&の違いは微妙で、一部はスタイルの問題ですが、時には正確性の問題もあります。ここでは一般的なケースをカバーするつもりはありません!

Forループに基づく範囲では、

for (auto element : container) {}

そして

for (auto& element_ref : container) {}

elementcontainer内の要素のコピーであり、element_refはコンテナ内の要素への参照です。

アクションの違いを確認するには、次の例を検討してください。

#include <iostream>

int main(void) {
    int a[5] = { 23,443,16,49,66 };

    for (auto i : a) i = 5;       
    for (const auto& i : a) std::cout << i << std::endl;
    for (auto& i : a) i = 5;   
    for (const auto& i : a) std::cout << i << std::endl;    
}

印刷します

23
443
16
49
66
5
5
5
5
5

なぜなら、最初のループは配列要素のコピーに対して機能し、2番目のループは実際に配列内の要素を変更するからです。

要素を変更したくない場合、多くの場合、const auto&の方が適切です。これは、要素のコピーを回避するためです(高価になる可能性があります)。