13

私たちが知っているように、ほとんどの場合、T&&「これは一時的なオブジェクトです」を意味します。ただし、関数から一時オブジェクトを返したい場合は、次のように関数を宣言できます。

template<class T>
T f()
{
    T t;
    ......

    return t;
}

または(注:正しくありません)

template<class T>
T&& f()
{
    T t;
    ......

    return t;
}

しかし、前者は十分で下位互換性があるため、後者はやり過ぎだと思います。

それでも、std::forward()の戻り型がT &&として宣言されていることもわかっているので、これについての私の理解は不完全であると確信しています。

私の本当の質問は、関数の戻り型をいつどこでT&&として宣言する必要があるかということです。

4

3 に答える 3

13

あなたの例では、T&&間違っています。ぶら下がっている参照です。

しかしstd::forward、それ自体の定義でローカル変数への右辺値参照を返すのではなく、右辺値参照による引数への右辺値参照 (または左辺値参照による引数への左辺値参照) を返します。

関数の呼び出し元がその参照が参照するものから移動できるようにする場合にのみ、右辺値参照を返す必要があります。

通常、これは、関数の目的が重要なオブジェクト (おそらく既に存在する) への移動アクセスを提供することである場合にのみ発生します。これにはstd::move(左辺値からの移動を可能にする) が含まれ、同様に、ユーザーがオブジェクトのデータ メンバーまたはコンテナーの要素から移動するように特別に設計されたアクセサー関数を作成することもできます。オブジェクト自体が重要ではなく、値のみの場合は、値で返すことができます。

grizzly が言うように、参照の崩壊が原因で、コードを入力 することを意味するトリックを利用できる場合がありますが、既に左辺値参照型が同じ左辺値参照型である場合があります。そのトリックを使用します。つまり、参照の崩壊は「T への右辺値参照」を意味しないため、「T が参照型の場合は T、そうでない場合は T への右辺値参照」を意味します。T&&TT&&std::forwardT&&

于 2013-01-30T14:01:22.247 に答える
4

T&&結果が右辺値であることを必ずしも意味するわけではありません。テンプレート パラメーターと共に使用する&&と、右辺値または左辺値参照のいずれかであるユニバーサル参照を示します。より具体的にTは、 が左辺値参照型foo&である場合、T&&実際には左辺値参照先fooであり、それ以外の場合は右辺値参照を示します。

これは、任意の種類の引数を取る関数を書くために使用できます。

template<typename T> void foo(T&&);
bar a;
const bar b;
foo(a);//T and T&& will both be bar&
foo(b);//T and T&& will both be const bar&
foo(bar());//T will be bar, T&& will be bar&&

これを念頭に置いてstd::forwardは a で呼び出され、それをにT&キャストします。したがって、元の関数パラメーターが左辺値参照であった場合は 1 を返し、それ以外の場合は右辺値参照を返し、完全な転送を可能にします。T&&T

戻り値の型としていつ使用するかについて: めったにありませんが、引数が渡されるときにコピーを避けると役立つ場合があります。次に例を示します。

template<typename T> T&& foo(T&& bar) {/*some ops*/ return std::forward<T>(bar);}
于 2013-01-30T13:55:53.427 に答える
2

答えは、関数がテンプレート関数かどうかによって異なります。あなたの質問ではそうでしたが、そうでない場合はまず見てみましょう:

非テンプレート

T&&戻り値の型として無意味ではありません。その理由は、実際には「一時的なオブジェクト」を意味しないからです。「右辺値参照」を意味します。違いは微妙ですが、この戻り値の型が関連する関数のクラスで強調できます。つまり、右辺値への参照を返したいが、それが参照するオブジェクトが関数のローカル オブジェクトではない場合はどうなるでしょうか。

T&& return_rvalue(/*some data*/)
{
   T&& t = Get_a_reference();
   // Do something fascinating.
   return static_cast<T&&>(t);
}

このパターンの非常に特殊なケースの 1 つが function です。この関数はstd::move、任意の参照を受け取り、対応する右辺値参照を返します。当然のことながら、実際のコードではstd::move、キャストを直接実行するのではなく、使用する必要があります。これにより、意図がより明確に示されます。

テンプレート

IfTはテンプレート パラメータであり、Scott Meyers がUniversal ReferenceT&&と呼んでいるものです。これは、の型が参照の折りたたみを使用して計算されることを意味します...要するに、参照型でない場合は右辺値であり、そうである場合は左辺値参照であることを意味します..T&&T&&T

于 2013-01-30T13:55:37.920 に答える