範囲ベースのループの例をいくつか読んで、2つの主な方法を提案します。 1 、 2 、、 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
}
まあ。
IMOのvec
アイテムを変更する必要がない場合、例では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
である間に、各反復で冗長コピーを回避しませんか?
avoidコピーを作成するだけでなく、アイテムを変更したくない場合は、auto const &
が正しい選択です。
for (auto const &x : vec)
auto &
の使用を勧める人は誰でも間違っています。それらを無視します。
要約は次のとおりです。
auto x
を選択します。auto &x
を選択します。auto const &x
を選択し、変更しません。std::vector<int>
またはstd::vector<double>
がある場合は、auto
またはint
をコピーするのが安価であるため、const auto&
の代わりにdouble
(値のコピーを使用)を使用しても問題ありません。
for (auto x : vec)
....
しかし、MyClass
にいくつかの重要なコピーセマンティクス(たとえば、std::vector<MyClass>
、いくつかの複雑なカスタムクラスなど)があるstd::string
がある場合は、const auto&
を使用してディープコピーを回避することをお勧めします:
for (const auto & x : vec)
....
vec
アイテムを変更する必要がない場合、最初のバージョンを使用することをお勧めします。
それから彼らは間違った提案をします。
Constが参照するものを提案しない理由
彼らは間違った提案を与えるからです:-)あなたが言うことは正しいです。 observeオブジェクトだけが必要な場合、コピーを作成する必要はなく、_const
以外の参照を持つ必要もありません。
編集:
リンクする参照はすべて、int
値の範囲またはその他の基本的なデータ型を反復処理する例を示しています。その場合、int
のコピーは高価ではないため、コピーの作成は基本的に、const &
を観察することと同等です(より効率的でない場合)。
ただし、これは一般的にユーザー定義型には当てはまりません。 UDTはコピーに費用がかかる場合があり、コピーを作成する理由がない場合(元のオブジェクトを変更せずに取得したオブジェクトを変更する場合など)、const &
を使用することをお勧めします。
ここで反対になりますが、forループに基づく範囲ではauto const &
は必要ありません。次の関数が馬鹿げていると思ったら教えてください(その目的ではなく、書かれている方法で):
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 &
をauto &
だけではなく、forループに基づく範囲の変数。