为什么我们不能投入T&&amp ;;的初始化T&变量还是T?

时间:2014-10-01 17:00:28

标签: c++

我正在寻找描述这一事实的规范性参考。我正在尝试以下方法:

#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()
{
}

DEMO

#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()
{
}

DEMO

我已阅读第8.3.2节,但找不到任何描述。

3 个答案:

答案 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