19

clang はn3994から簡潔な範囲ベースの for ループの実装を開始しました。範囲ベースの for ループを導入する場合、不必要なコピーを避けるために の形式のコードがよく見られます。n3994はあらゆる点で優れていると提案しているようです。いくつかの質問を聞きたいんです:for (auto & v : vector)for (auto && v : vector)

  1. 後者の形式は前者よりもどのような利点がありますか? 後者が明らかに有利であるのに、なぜ私たちは通常auto &代わりにそれを採用するのでしょうか?auto &&
  2. auto &&新しい ranged-for ベースのループを作成することは、既存のコードを壊すことと同等ですか? それは新しいコードに実際の影響を与えるでしょうか?
  3. これは、コードが実際に同等である初心者に落とし穴をもたらしませんauto &&か?
4

2 に答える 2

10

後者の形式は前者よりもどのような利点がありますか?

の形式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&非対称。

于 2014-08-24T04:34:02.043 に答える
8

後者の形式は前者よりもどのような利点がありますか? 後者が明らかに有利であるのに、なぜ私たちは通常auto &代わりにそれを採用するのでしょうか?auto &&

auto &非 const 左辺値参照を一時にバインドしようとするため、イテレータの逆参照が実際の参照ではなくプロキシ オブジェクトを返す場合は機能しません。標準的な例は、として知られている忌まわしきものstd::vector<bool>です。その反復子を逆参照するstd::vector<bool>::referenceと、ベクター内の単一ビットを表す型のプロキシ オブジェクトが返されます。ほとんどの反復子は実際の参照を返すため、この問題に頻繁に遭遇することはありません。

auto && と同等の新しい ranged-for ベースのループを作成すると、既存のコードが壊れますか? それは新しいコードに実際の影響を与えるでしょうか?

いいえ、新しい構文for(elem : range)は既存のコードではコンパイルされないためです。

これは、コードが実際に同等である初心者に落とし穴をもたらしませんauto &&か?

なぜ落とし穴になるのですか?auto &&実際にはすべてに機能するという利点があります。初心者に型推論や参照の折りたたみなどの詳細をすべて教える必要がないことは、言語の学習が容易になるため、実際にはプラスであると主張する人もいるかもしれません。

于 2014-08-24T04:26:48.577 に答える