7

右辺値参照を理解するために、コンパイラーが特定の関数の引数が右辺値参照であると判断するのはいつか、それが左辺値参照であるとコンパイラーが判断するのはいつかを考えてきました。

(この問題は参照の折りたたみに関連しています。要求された参照の折りたたみルールの簡潔な説明を参照してください:(1)A &&-> A&、(2)A &&&-> A&、(3)A &&&-> A&、および(4)A && &&-> A &&)。

特に、コンパイラが常に名前のないオブジェクトを右辺値参照として扱うかどうか、および/またはコンパイラが一時オブジェクトを常に右辺値参照として扱うかどうかを検討してきました。

次に、これにより、名前のないオブジェクトが一時的なオブジェクトと同等であるかどうかを疑問視することになります。

私の質問は次のとおりです。名前のないオブジェクトは常に一時的なものですか。一時オブジェクトは常に名前がありませんか?

言い換えると、名前のないオブジェクトと一時的なオブジェクトは同等ですか?

4

3 に答える 3

3

「名前のないオブジェクト」の定義がわからないので、私は間違っているかもしれません。ただし、以下のfoo()関数の引数について考えてみます。

void foo(int)
{ /* ... */ }

int main()
{ foo(5); }

foo()の引数には名前がありませんが、一時的なものではありません。したがって、名前のないオブジェクトと一時オブジェクトは同等ではありません。

于 2012-12-05T18:31:27.500 に答える
3

一時的なオブジェクトに名前を付けることができます。

非常に一般的なケース-パラメーターとして関数に渡される場合。もう1つのあまり一般的ではないケース-const参照を関数の右辺値の結果にバインドします。

int f(int i) { return i + 1; }
int g() { const int &j = f(1); return j; }

名前のないオブジェクトは一時的なものであることがよくありますが、常にそうとは限りません。例-匿名ユニオンオブジェクト:

struct S
{
   union { int x; char y; };
} s;

そしてもちろん、によって作成されたオブジェクトoperator new

おそらく他のケースもありますが、これらだけでも仮説の反例として役立ちます:)

于 2012-12-05T18:40:17.410 に答える
2

コンパイラが特定の関数の引数が右辺値参照であると判断するのはいつか、それが左辺値参照であるとコンパイラーが判断するのはいつか、私は考えていました。

このように、ユニバーサル参照パラメーターを使用した関数テンプレートについて話していると思いますか?

template<typename T>
void foo(T&& t)
{
}

ルールはとてもシンプルです。引数が型の右辺値である場合、はとX推定TされX、したがって、T&&を意味しX&&ます。X引数がタイプの左辺値である場合、はとT推定されますX&。したがって、T&&X& &&、に折りたたまれX&ます。

引数について本当に質問している場合、引数は左辺値参照または右辺値参照になることはないため、質問はあまり意味がありません。型の式は、参照されるオブジェクトを示すX&型の式にすぐに変換されるためです。X

しかし、実際に「コンパイラは左辺値引数と右辺値引数をどのように区別するのですか?」という意味の場合。(参照が欠落していることに注意してください)、答えは簡単です。標準では、考えられるすべての式に対してその値のカテゴリが指定されているため、コンパイラはすべての式の値のカテゴリを認識しています。たとえば、関数の呼び出しは、次の3つの値のカテゴリのいずれかに属することができる式です。

X   foo();   // the expression foo() is a prvalue
X&  bar();   // the expression bar() is an lvalue
X&& baz();   // the expression baz() is an xvalue

(もちろん、それX自体が参照型ではない場合に限ります。)

これのどれもあなたの質問に答えないならば、質問を明確にしてください。また、やや関連性のあるFAQ回答

于 2012-12-05T19:00:16.333 に答える