rvalues、lvalues、xvalues、glvalues、およびprvaluesとは何ですか?rvalues / lvaluesの分類法の概要を示し、その質問に対する最近の回答の1つ(https://stackoverflow.com/a/9552880/368896)は、prvaluesが古いスタイルのrvaluesに「似ている」という点を強調しています。 、一方、新しいxvalueは、「左辺値のような」動作を可能にします。
ただし、次のコードを検討してください。
class X {};
X foo() { return X(); }
int main()
{
foo() = X(); // foo() is a prvalue that successfully appears on the lhs
}
この例では、式foo()
は左側に表示されるprvalueであり、割り当てを受け入れます。
それは私に考えさせられました-xvalues(それらがそうであるglvalues)が左側に現れることができるので、「xvalues」が「prvalues」と異なるという論理は、この例によって壊れているようです。ここでは、prvalue(glvalueではありません)がlhsに正常に表示され、割り当てを受け入れています。
(注:PODの場合、上記の例はコンパイルされないため、PODの場合、xvaluesとprvaluesの区別は理にかなっているようです。したがって、この質問は特に非PODタイプに関するものです。)
では、xvalueとprvalueの間で許可される使用法または動作の真の違いは何であり、この区別を標準に書き込む必要がありますか?違いの1つの例は、優れた代替回答です。
補遺
パビーのコメントは正しかった。prvalueの存続期間はコンパイラーによって延長されますが、xvalueの存続期間は延長されません。
だから、ここに質問への答えがあります:
次のコードを検討してください。
// ***
// Answer to question, from Pubby's comment
// ***
class X
{
public:
X() : x(5) {}
int x;
};
X foo() { return X(); }
X&& goo() { return std::move(X()); } // terrible coding, but makes the point
int main()
{
foo() = X();
X&& x1 = foo(); // prvalue - lifetime extended! Object resides directly on stack as return value
X&& x2 = goo(); // xvalue - lifetime not extended. Object (possibly polymorphic) resides somewhere else.
x1.x = 6;
x2.x = 7; // Danger!
std::cout << x1.x << std::endl; // Just fine
std::cout << x2.x << std::endl; // prints garbage in VS 2012
}
これは、prvalueとxvalueの動作の違いを示しています。ここでは、バインディングの違い(prvalueとxvalue)を除いて、同じクライアントコードがあります。
サンプルコードが示すように、prvalueの有効期間は自動的に延長されますが、xvalueの有効期間は延長されません。
他にも明らかな違いがあります。prvalueの場合、オブジェクト自体が関数の戻り値としてスタックに表示されます。これに対応して、prvalueの静的型は動的型であることが保証されているため(以下の回答を参照)、その存続期間を延長することは意味があり、コンパイラーによって実行できます。
一方、xvalueの場合、オブジェクトは未知の任意の場所にあるため、特に型が多形である可能性がある場合、コンパイラーはその存続期間を簡単に延長できませんでした。
答えてくれてありがとう。