2012-04-19 21 views
2

誰かがBがコンパイルされない理由を説明することはできますか?変数が既にrvalue refなので、std :: moveが必要な理由は分かりません。rvalue refsとstd :: move

struct A { 
    int x; 
    A(int x=0) : x(x) {} 
    A(A&& a) : x(a.x) { a.x = 0; } 
}; 

struct B : public A { 
    B() {} 
    B(B&& b) : A(b) {} // compile error with g++-4.7 
}; 

struct C : public A { 
    C() {} 
    C(C&& c) : A(std::move(c)) {} // ok, but why? 
}; 
+0

答えを受け入れる:

は、私は非常に有用(もともとビャーネ・ストロヴストルップによって発明)以下の図を見つけて下さい! – Walter

答えて

12

という名前の変数が& &を宣言した場合でも、右辺値ではありませんので。一時的な名前でない場合は、std::moveを使用する必要があります。声明の中で

21

Bへの右辺値参照:

B(B&& b) 

パラメータbは型で宣言されています。声明の中で

A(b) 

表現bはタイプBの左辺値です。

そして、左辺値式は右辺値参照にバインドできません:文で、具体的右辺値参照:

A(A&& a) 

このロジックは、言語の他の部分からきれいに従います。この関数を考えてみましょう:

void 
f(B& b1, B b2, B&& b3) 
{ 
    g(b1); 
    g(b2); 
    g(b3); 
} 

fのパラメータはすべての異なる種類を使用して宣言されているにもかかわらず、表現b1b2b3は、すべてのタイプBの左辺値式であるため、すべてのノー、同じ機能gを呼び出しますどのようにgに過負荷がかかっているかどうか。

C++ 11では、変数の宣言と、その変数の使用に起因する式を区別することがこれまで以上に重要です。表現には参照型はありません。代わりに、の値カテゴリがあります:lvalue、xvalue、prvalue。

声明:std::moveは右辺値参照を返すため

A(std::move(c)) 

は、okです。 rvalue参照を返す関数呼び出しの結果として得られる式には、値category:xvalueがあります。そして、prvaluesと一緒に、xvaluesはrvaluesとみなされます。そして、タイプCの右辺値の式:A(A&& a)

std::move(c) 

はで右辺値参照パラメータにバインドします。

 expression 
     /\ 
    glvalue rvalue 
    /\ /\ 
lvalue xvalue prvalue 
+0

その詳細な答えをありがとう。明らかにここには微妙な理解がたくさんあります。 – drwowe

関連する問題