[英]Why can you indirectly bind an rvalue to an lvalue reference but not directly?
从我阅读和看到的内容来看,您无法将作为右值的表达式绑定到左值引用。 但是,我看到的是可以将右值绑定到右值引用,并且由于命名的右值引用本质上是左值,因此可以将其绑定到左值引用。 不允许将右值绑定到左值引用的原因是什么? 是出于优化目的吗?
举个例子:
#include <iostream>
using std::cout;
void bar ( int& b ) {
cout << "bar " << b << "\n";
b = 3;
}
void foo ( int&& a ) {
cout << a << "\n";
bar(a);
cout << a << "\n";
}
int main ( int argc, char ** argv ) {
foo(1);
}
这是C ++的基本规则,可防止错误:
int foo();
int& x = 3; // whoops
int& y = foo(); // whoops (sometimes)
至少部分地创建了“ Rvalue引用”(一组类型;不要与实际的rvalue混淆),以便在您确实想要执行以下操作时仍可以执行此操作:
int&& x = 3; // oh, go on then *sigh*
int&& y = foo(); // you'd better be sure!
在前面的示例中,我将右值表达式“引用”的对象绑定(或尝试绑定)到引用。
现在,我将由左值表达式命名的对象绑定到引用:
int i = foo();
int& x = i; // no problem michael
并且要确保您确实打算从左值表达式中获取右值引用,并引入了一个名字难以置信的std::move
:
int&& x = std::move(i); // doesn't move anything
这些后来的规则比起最初的基本规则要晚得多,而过去的基本规则无疑在过去20年中避免了许多错误。
请注意,Visual Studio历史上一直接受T& x = bar()
,其中T
是用户定义的类型。 去搞清楚。
不允许将右值绑定到左值引用的原因是什么?
如果不参考Bjarne Stroustrup的无价宝贵著作《 C ++的设计和演变》,就不可能完全解决这个问题。
Bjarne在3.7节中写道:
但是,我犯了一个严重的错误,即允许使用非左值初始化非
const
引用。 例如:void incr(int& rr) { rr++; } void g() { double ss = 1; incr(ss); // note: double passed, int expected // (fixed: error in Release 2.0) }
由于类型不同,
int&
不能引用传递的double
因此生成了一个临时文件来保存由ss
值初始化的int
。 因此,incr()
修改了临时变量,结果没有反映回调用函数。
我强烈建议使用C ++的设计和演化,以理解一个人可能会有的许多“为什么问题”,尤其是有关在C ++ 98标准之前制定的规则的问题。 这是该语言的丰富而有趣的历史。
当您调用foo(1)
,将创建一个等于1
的临时int
,并将int&& a
绑定到它。 您可以自由更改。 用相同的方式可以写int&& a = 1;
。 a
本身就是一个左值,所以你可以参考左值绑定到它。
您可能会读到Scott Meyers撰写的出色文章Universal References ,其中详细介绍了右值和左值引用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.