18

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の場合、オブジェクトは未知の任意の場所にあるため、特に型が多形である可能性がある場合、コンパイラーはその存続期間を簡単に延長できませんでした。

答えてくれてありがとう。

4

2 に答える 2

7

ポリモーフィックな非ポッド型の xvalue 式の場合、式の動的な型は一般にコンパイル時に不明です (そのため、それらの typeid 式が評価され、仮想関数呼び出しは一般に非仮想化できません)。

prvalues の場合、これは当てはまりません。動的タイプは静的タイプと同じです。

もう 1 つの違いは、decltype(e)xvalue は右辺値参照型であり、prvalue は非参照型であることです。

さらに別の違いは、左辺値から右辺値への変換が prvalues に対して行われないことです (それらはすでに結果が得られるものです)。これは、かなり奇妙なコードで確認できます

struct A { 
    int makeItANonPod; 
    A() = default;

  private:
    int andNonStdLayout;
    A(A const&) = default;
};

void f(...);

int main() {
  f(A()); // OK
  f((A&&)A()); // illformed
}
于 2013-03-18T17:44:41.443 に答える
0

xvalue と prvalue の本当の違いは何ですか? xvalue は、cv 修飾され、オブジェクトを参照し、動的型が静的型と等しいか等しくない右辺値の一種です。

const int&& foo();
int&& _v=foo();

xvalue がない場合、上記の関数 foo の戻り値は右辺値のみになります。しかし、組み込み型には const 右辺値がありません! したがって、上記の非 const 変数 _v は、foo() が const 右辺値を返したい場合でも、常に foo() の戻り値をバインドできます。

于 2014-07-29T06:46:40.973 に答える