什么是右值,左值,x值,glvalues和prvalues?对rvalues/lvalues的分类进行了很好的概述,最近对该问题的回答之一(/sf/answers/668701631/)强调了prvalues"喜欢"旧式rvalues的观点而新的xvalues允许"左值"行为.
但是,请考虑以下代码:
class X {};
X foo() { return X(); }
int main()
{
foo() = X(); // foo() is a prvalue that successfully appears on the lhs
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,表达式foo()
是出现在左侧的prvalue,并接受赋值.
这让我思考 - "xvalues"与"prvalues"的逻辑不同,因为xvalues(它们是glvalues)可能出现在左侧,似乎被这个例子打破了.在这里,我们有一个prvalue - 这不是一个glvalue - 成功地出现在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
}
Run Code Online (Sandbox Code Playgroud)
这证明了prvalue和xvalue之间的行为差异.这里我们有相同的客户端代码,除了绑定的差异(prvalue与xvalue).
如示例代码所示,prvalue的生命周期自动扩展,但xvalue的生命周期不是.
还有其他显而易见的差异:对于prvalue,对象本身作为函数的返回值出现在堆栈上; 相应地,因为prvalue的静态类型保证是它的动态类型(见下面的答案),延长它的生命周期是有意义的,可以由编译器完成.
另一方面,对于xvalue,对象位于某个未知的任意位置,因此编译器无法轻松延长其生命周期,特别是考虑到类型可能是多态的.
谢谢你的回答.
对于多态nonpod类型xvalue表达式,表达式的动态类型在编译时通常是未知的(因此评估它们上的typeid表达式,并且通常不能虚拟化虚函数调用).
对于prvalues,这不适用.动态类型等于静态类型.
另一个区别是decltype(e)
xvalues的rvalue引用类型和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
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1213 次 |
最近记录: |