xvalue和prvalue FOR NON-POD对象之间允许的使用或行为有何不同?

时间:2013-03-18 16:58:49

标签: c++ c++11 rvalue

What are rvalues, lvalues, xvalues, glvalues, and prvalues?对rvalues / lvalues的分类进行了很好的概述,最近对该问题的回答之一(https://stackoverflow.com/a/9552880/368896)强调了prvalues“喜欢”旧式rvalues的观点。 ,而新的xvalues允许“左值”行为。

但是,请考虑以下代码:

class X {};
X foo() { return X(); }

int main()
{
    foo() = X(); // foo() is a prvalue that successfully appears on the lhs
}

在此示例中,表达式foo()是出现在左侧的prvalue,并接受赋值。

这让我思考 - “xvalues”与“prvalues”的逻辑不同,因为xvalues(它们是glvalues)可以出现在左侧,似乎被这个例子打破了。在这里,我们有一个prvalue - 它不是一个glvalue - 成功地出现在lhs并接受任务。

(注意:在POD的情况下,上面的例子不会编译,所以对于POD,xvalues和prvalues之间的区别似乎是有意义的。因此,这个问题特别针对非POD类型。)< / p>

然后,xvalue和prvalue之间的允许使用或行为的真正区别在于,是否需要将此区别写入标准?差异的一个例子是一个很好的替代答案。

附录

Pubby的评论是正确的。 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,对象位于某个未知的任意位置,因此编译器无法轻松延长其生命周期,特别是考虑到该类型可能是多态的。

感谢您的回答。

2 个答案:

答案 0 :(得分:6)

对于多态nonpod类型xvalue表达式,表达式的动态类型在编译时通常是未知的(因此评估它们上的typeid表达式,并且通常不能虚拟化虚函数调用)。

对于prvalues,这不适用。动态类型等于静态类型。

另一个区别是decltype(e)是xvalues的右值引用类型和prvalues的非引用类型。

另一个不同之处在于没有为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
}

答案 1 :(得分:0)

xvalue和prvalue之间的真正区别是什么? xvalue是一种rvalue,可以是cv限定的,引用一个对象,并且动态类型等于或不等于静态类型。

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

如果没有xvalue,上述函数foo的返回值只能是rvalue。但是内置类型没有const rvalue!因此,上面的非const变量_v总是可以绑定foo()的返回值,即使我们希望foo()返回一个const rvalue。