2

通常、私はそのようなコードを書きます。

auto elements = get_elements();
for(auto i : elements)
{
    // ...
}

代わりに以下のコードを使用すると、パフォーマンスに違いが生じるのではないかと思います。反復ごとに呼び出されますかget_elements()、それとも一度だけ呼び出されますか?

for(auto i : get_elements())
{
    // ...
}

さらに、従来の for ループはどうでしょうか。ループする要素を変更しない場合、コンパイラはそのコードを最適化して、get_elements()すべての反復を呼び出さないようにしますか?

for(auto i = get_elements().begin(); i != get_elements().end(); ++i)
{
    // ...
}
4

1 に答える 1

2

代わりに以下のコードを使用すると、パフォーマンスに違いが生じるのではないかと思います

いつものように、パフォーマンスに関しては、測定値で仮定をバックアップする必要があります。

その特定のルーチンにボトルネックがあることを示す明確な測定以外の証拠は、より複雑で直感的でないデザインを優先して、より明確でシンプルなデザインを放棄する理由になるはずです. それは、定義上、時期尚早の最適化です。

したがって、その意図を最もよく伝えるフォームを選択してください。これは言った、私は次の質問に答えることができます:

反復ごとに呼び出されますかget_elements()、それとも一度だけ呼び出されますか?

いいえ、一度だけ呼び出されます。この動作は、C++11 標準のパラグラフ 6.5.4/1 で義務付けられています。

形式の範囲ベースの for ステートメントの場合

for ( for-range-declaration : expression ) statement

括弧range-initで囲まれた式と同等にする

( expression )

[...] 範囲ベースの for ステートメントは次と同等です

{
    auto && __range = range-init; // <== HERE IS YOUR get_elements()!
    for ( auto __begin = begin-expr,
        __end = end-expr;    
        __begin != __end;
        ++__begin ) {
            for-range-declaration = *__begin;
            statement
        }
    }

2番目の質問について:

さらに、従来の for ループはどうでしょうか。

これらは、ループ自体の目的が明確ではなく、エラーが発生しやすくなっています。手動ループを避けることをお勧めします。

たとえば、最初の行を見るだけで、範囲ベースのforループの目的がコレクションのすべての要素を反復処理することであることが明らかです。

同じことは手動で展開されたループでは明らかではなく、最初の行を見るだけでは、変数がループ内で増分または操作されるforかどうかわかりません。i

これについては、Herb Sutter によるこの記事でうまく説明されています (質問 2-a の解決策を参照してください)。

于 2013-05-17T11:33:11.083 に答える