267

範囲ベースのループのいくつかの例を読むと、2つの主な方法が示唆ます1、2、3、4

std::vector<MyClass> vec;

for (auto &x : vec)
{
  // x is a reference to an item of vec
  // We can change vec's items by changing x 
}

また

for (auto x : vec)
{
  // Value of x is copied from an item of vec
  // We can not change vec's items by changing x
}

上手。

アイテムを変更する必要がない場合vec、IMO、例では2番目のバージョン(値による)を使用することをお勧めします。なぜ彼らはconst参照する何かを提案しないのですか(少なくとも私は直接の提案を見つけていません):

for (auto const &x : vec) // <-- see const keyword
{
  // x is a reference to an const item of vec
  // We can not change vec's items by changing x 
}

良くないですか?それがである間、それは各反復で冗長なコピーを避けませんconstか?

4

5 に答える 5

468

アイテムを変更したくないだけでなく、コピーを作成したくない場合auto const &、正しい選択です。

for (auto const &x : vec)

使用を提案する人は誰でもauto &間違っています。それらを無視します。

ここに要約があります:

  • コピーを操作するタイミングを選択auto xします。
  • auto &xオリジナルのアイテムをいつ操作するかを選択し、それらを変更することができます。
  • 元のアイテムを操作するタイミングを選択auto const &xし、それらを変更しません。
于 2013-03-02T15:27:29.477 に答える
31

またはを使用している場合は、std::vector<int>またはのコピーは安価であるため、の代わりに(値のコピーstd::vector<double>を使用して)使用しても問題ありません。autoconst auto&intdouble

for (auto x : vec)
    ....

しかし、std::vector<MyClass>いくつMyClassかの重要なコピーセマンティクス(たとえばstd::string、いくつかの複雑なカスタムクラスなど)がある場合はconst auto&、ディープコピーを避けるために使用することをお勧めします:

for (const auto & x : vec)
    ....
于 2013-03-02T15:33:07.820 に答える
3

アイテムを変更する必要がない場合vec、例では最初のバージョンを使用することをお勧めします。

それから彼らは間違った提案をします。

constが参照するものを提案しない理由

彼らは間違った提案をしているので:-)あなたが言っていることは正しいです。オブジェクトのみを観察したい場合は、コピーを作成する必要はなく、オブジェクトへの非const参照を持つ必要もありません。

編集:

リンクしている参照はすべて、int値の範囲またはその他の基本的なデータ型を反復処理する例を提供しているようです。その場合、コピーintを作成するのは費用がかからないため、コピーを作成することは、基本的に(より効率的ではないにしても)監視を行うことと同等const &です。

ただし、これは一般にユーザー定義型には当てはまりません。UDTのコピーにはコストがかかる可能性があり、コピーを作成する理由がない場合(元のオブジェクトを変更せずに取得したオブジェクトを変更するなど)、を使用することをお勧めしますconst &

于 2013-03-02T15:28:12.487 に答える
1

auto const &ここでは反対になり、forループに基づく範囲では必要がないと言います。次の関数がばかげていると思うかどうか教えてください(その目的ではなく、記述方法で):

long long SafePop(std::vector<uint32_t>& v)
{
    auto const& cv = v;
    long long n = -1;
    if (!cv.empty())
    {
        n = cv.back();
        v.pop_back();
    }
    return n;
}

vここで、作成者はvを変更しないすべての操作に使用するconst参照を作成しました。これは私の意見ではばかげてauto const &おり、forループに基づく範囲の変数として使用するために同じ引数を作成できます。 auto &

于 2013-03-02T16:03:12.223 に答える
1

私は考えます

for (auto&& o : range_expr) { ...}

また

for (auto&& o : std::as_const(range_expr)) { ...}

それは常に機能します。

一時的な範囲表現の落とし穴に注意してください。

C ++ 20では、次のようなものがあります

for (T thing = foo(); auto& x : thing.items()) { /* ... */ }
于 2020-10-31T11:48:11.480 に答える