对于非pod对象,xvalue和右值在允许使用或行为方面的差异示例是什么?
What is an example of a difference in allowed usage or behavior between an xvalue and a prvalue FOR NON-POD objects?
什么是右值、左值、左值、右值和右值?对右值/左值的分类进行了很好的概述,最近对这个问题的一个回答(https://stackoverflow.com/a/9552880/368896)强调了左值"类似于"老式的右值,而新的xvalue允许"类似于左值"的行为。
但是,考虑以下代码:
class X {};
X foo() { return X(); }
int main()
{
foo() = X(); // foo() is a prvalue that successfully appears on the lhs
}
在本例中,表达式foo()
是出现在左侧的右值,并接受赋值。
这让我思考-"x值"不同于"右值"的逻辑,因为x值(它们是glvalues)可以出现在左侧,似乎被这个例子打破了。这里我们有一个右值——它不是左值——在lhs上成功出现并接受赋值。
(注意:在POD的情况下,上面的示例无法编译,因此对于POD, xvalue和前值之间的区别似乎是有意义的。因此,这个问题是专门针对非pod类型的。)
那么,在允许的用法或行为上,xvalue和prvalue之间的真正区别是什么,以至于需要将这种区别写入标准?举一个不同的例子就是一个很好的替代答案。附录
Pubby的评论是正确的。编译器会扩展右值的生存期,但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在行为上的不同。这里我们有相同的客户端代码,除了绑定的不同(prvalue和xvalue)。
如示例代码所示,右值的生存期会自动延长,但xvalue的生存期不会。
还揭示了其他明显的区别:对于右值,对象本身作为函数的返回值出现在堆栈上;相应地,因为右值的静态类型保证是它的动态类型(见下面的答案),所以延长它的生命周期是有意义的,并且可以由编译器完成。
另一方面,对于xvalue,对象位于某个未知的任意位置,因此编译器无法轻松地延长其生命周期,特别是考虑到该类型可能是多态的。
谢谢你的回答
对于多态非pod类型xvalue表达式,表达式的动态类型通常在编译时是未知的(因此对它们的类型id表达式进行计算,并且虚拟函数调用通常不能去虚拟化)。
对于左值则不适用。动态类型等于静态类型
另一个区别是decltype(e)
是xvalues的右值引用类型,而右值的非引用类型。
另一个区别是左值到右值的转换不是对右值进行的(它们已经是结果将产生的)。这可以通过一些相当奇怪的代码
观察到。struct A {
int makeItANonPod;
A() = default;
private:
int andNonStdLayout;
A(A const&) = default;
};
void f(...);
int main() {
f(A()); // OK
f((A&&)A()); // illformed
}
x值和右值之间的真正区别是什么?xvalue是一种可以被cv限定的右值,引用对象,其动态类型等于或不等于静态类型。
const int&& foo();
int&& _v=foo();
如果没有xvalue,上述函数foo的返回值只能是右值。但是内置类型没有const右值!因此,上述非const变量_v总是可以绑定foo()的返回值,即使我们希望foo()返回一个const右值。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- C++避免重复声明的语法是什么
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- C++从另一个类访问公共静态向量的正确方法是什么
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- C++中名称篡改的目的是什么
- 在 c++ 中拥有一组结构的正确方法是什么?
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 是什么阻止DOMTimerCoordinator::NextID进入无休止的循环
- 派生类销毁的最佳实践是什么
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- 通过JNI传递数据数组的最快方法是什么
- "using namespace std;"在C++的作用是什么?
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 文件系统:复制功能的速度秘诀是什么
- 在插入时同时迭代一个映射,这在什么方面是不安全的
- 在内存使用或编译时间方面更好的是什么
- 对于非pod对象,xvalue和右值在允许使用或行为方面的差异示例是什么?
- 测试值是否在阈值范围内的最佳方法(性能方面)是什么