什么是x值和prevalue FOR NON之间的允许使用或行为差异的例子
什么是右值,左值,xvalues,glvalues和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)可以出现在左边,这个例子似乎被打破了。 在这里,我们有一个价值 - 这不是一个血统 - 在lhs上成功出现并接受任务。
(注意:在POD的情况下,上面的例子不会编译,所以对于POD,xvalues和prvalues之间的区别似乎是有意义的,因此,这个问题是专门针对非POD类型的。)
那么,在一个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
}
这证明了一个前值和一个xvalue之间的行为差异。 这里我们有相同的客户端代码,除了绑定的区别(前值与xvalue)之外。
如示例代码所示,prvalue的生命周期会自动扩展,但xvalue的生命周期不是。
还有其他显而易见的差异:对于prvalue,对象本身作为函数的返回值出现在堆栈上; 相应地,因为prvalue的静态类型被保证是它的动态类型(见下面的答案),所以延长它的生命周期是有意义的,可以由编译器完成。
另一方面,对于xvalue,该对象位于某个未知的任意位置,因此编译器无法轻松延长其生命周期,特别是考虑到该类型可能是多态的。
感谢你的回答。
对于多态非pod类型的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
}
xvalue和prvalue之间的真正区别是什么? xvalue是一种右值,它可以被cv限定并引用一个对象 ,并且动态类型与静态类型相等或不相等。
const int&& foo();
int&& _v=foo();
没有xvalue,上述函数foo的返回值只能是右值。 但是,内建类型不具有常量值! 因此,上面的非常量变量_v总是可以绑定foo()的返回值,即使我们希望foo()返回一个const rvalue。
链接地址: http://www.djcxy.com/p/12679.html