後者の形式は前者よりもどのような利点がありますか?
の形式for(auto& v : vector)
では、 の型はv
、コンテナーの反復子型を逆参照することによって取得された型への左辺値参照として推定されます。これは、反復子を逆参照した結果が右辺値 (std::vector<bool>
単一の値への参照を表すプロキシ型を返すと考えてくださいbool
) である場合、左辺値参照は右辺値にバインドできないため、コードはコンパイルに失敗することを意味します。
を記述するfor(auto&& v : vector)
と、これはユニバーサル参照になります。つまり、上記の場合、 の型はv
右辺値参照として推定されます。または、イテレータを逆参照するとコンテナの要素への参照が返される通常のケースでは、左辺値参照として。したがって、vector<bool>
ケースでも機能します。そのため、ループ内で繰り返し処理している要素を変更する予定がある場合は、その形式を優先する必要があります。
後者が明らかに有利であるのに、なぜ私たちは通常auto&
代わりにそれを採用するのでしょうか?auto&&
すべきではありません。私が考えることができる唯一の欠点はauto&&
、要素に加えた変更が必ずしもコンテナーに反映されることを保証しないことですが、それは設計が壊れていることを示しており、保護する価値はないと思います.
auto &&
新しい ranged-for ベースのループを作成することは、既存のコードを壊すことと同等ですか?
古い構文は現在と同じように引き続き機能するため、既存のコードがどのように壊れるかはわかりません。ただし、既存のコードを新しい構文に置き換えることを意味する場合、置き換えるものがauto const&
フォームである場合に影響がある可能性があります。この例を参照してください。auto const&
バージョンがconst
メンバー関数を呼び出し、他の 2 つは非const
バージョンを呼び出す方法に注意してください。最初のものを簡潔なバージョンに置き換えると、呼び出されるメンバー関数が変更されます。
それは新しいコードに実際の影響を与えるでしょうか?
auto&&
繰り返しますが、今日使用されている古いコードと何ら変わりはないので、違いはありません。要素を変更する予定のない場所で使用すると、コンパイラは誤ってそれを行うことを止めなくなり、上記の例に示すように、別のオーバーロードを呼び出す可能性があります。
これは、コードが実際に同等である初心者に落とし穴をもたらしませんauto &&
か?
これが何を意味するのかよくわかりませんが、初心者が知らないうちにコードを書いたり、参照の崩壊の複雑さを理解したりするかどうかを尋ねているなら、はい、そうなる可能性があります。しかし、それはあなたがリンクした論文の目標の 1 つです。これらの難しい概念を最初から教えないようにすることはできますが、初心者には、for
すべてで機能する範囲ベースのループの単一の構文を紹介してください。それに関しては、構文にはメリットがあると思いますが、正確性の観点から見ると、要素への読み取り専用アクセスが必要な場合const
はむしろ使用したいので、私はそれを眉をひそめます。auto const&
非対称。