我正在寻找描述这一事实的规范性参考。我正在尝试以下方法:
#include <iostream>
int z = 4;
int &a = z;
int &&b = a; //error: rvalue reference to type 'int'
//cannot bind to lvalue of type 'int'
int main()
{
}
#include <iostream>
int z = 4;
int &a = z;
int &&b = z; //error: error: rvalue reference to type 'int'
//cannot bind to lvalue of type 'int'
int main()
{
}
我已阅读第8.3.2节,但找不到任何描述。
答案 0 :(得分:4)
8.5.3 [dcl.init.ref]第5段。
第一个项目符号定义了左值引用的绑定左值。第二个项目描述了其他形式的引用初始化,它必须是对const或rvalue引用的左值引用,并且可以绑定到xvalues,prvalues等但不能绑定左值。
在N2844中解释了从左值不允许初始化右值引用的原因。
答案 1 :(得分:2)
关于rvalue引用的一个有用的直觉是它们传达了被引用对象的部分“所有权” - rvalue引用引用的对象不会被任何其他方式访问,因此您可以自由地修改对象(窃取已经分配的内存是常见的情况)没有“惊讶”任何其他可能以某种其他方式引用该对象的人。 rvalue引用的重点是允许基于“移动”的语义,您可以在其中移动并回收资源(而不是分配新资源)。
这表明上述例子是错误的原因。如果你允许的话
int z;
int &&b = z;
那么你会遇到一个案例,其中rvalue引用(b)引用的对象仍然可以通过其他名称(z)访问。如果你想能够做到这一点,你需要明确地做到
int z;
int &&b = std::move(z);
在这种情况下,您(有效地)说“在此之后我不关心名字'z'”。当编译器超出范围时,编译器仍将跟踪它以清理任何(剩余)资源,但程序不关心它或其值。在int
对象的情况下,没有任何其他资源可以窃取/移动,所以这一切都没有意义。另一方面,对于像集合这样的复杂对象,这可以显着提高性能。
答案 2 :(得分:-2)
首先,您必须移动对象以获得右值:
int &&b = std::move(z);
你可以这样想:如果发生移动,z
会丢失其状态并将其交给b
。