繁体   English   中英

为什么我们不能在T &&的初始化程序中放入T&或T的变量?

[英]Why can't we put into initializer of T&& a variable of T& or T?

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

#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节,但是找不到任何描述。

8.5.3 [dcl.init.ref]第5段。

第一个项目符号定义将左值绑定到左值引用。 第二个项目符号描述了引用初始化的其他形式,这些形式必须是用于const或rvalue引用的左值引用,并且可以绑定到xvalues,prvalues等,但不能绑定到lvalues。

N2844中说明了禁止从左值初始化右值引用的原因。

关于右值引用的一种有用的直觉是,它们传达了所引用对象的部分“所有权”-右值引用所引用的对象将无法通过其他任何方式进行访问,因此您可以自由地修改对象(窃取内存)分配它是常见的情况),而不会“让”其他可能以其他方式引用该对象的人感到惊讶。 右值引用的全部要点是基于“移动”的语义,您可以在其中移动和回收资源(而不是分配新资源)。

这说明了上面的示例为什么是错误的。 如果允许的话

int z;
int &&b = z;

那么您将遇到一个情况,即右值引用(b)所引用的对象仍可以通过其他名称(z)访问。 如果您希望做到这一点,则需要明确地做到这一点

int z;
int &&b = std::move(z);

在这种情况下,您是说(有效)“在此之后,我不在乎'z'这个名称”。 超出范围时,编译器仍会跟踪它以清除任何(剩余)资源,但是程序并不关心它或它的值。 对于int对象,没有任何其他资源可以窃取/移动,因此这一切都毫无意义。 另一方面,对于像集合这样的复杂对象,这可以显着提高性能。

首先,您必须移动对象以获得右值:

int &&b = std::move(z);

您可以这样想:如果发生移动, z丢失其状态并将其交给b

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM