繁体   English   中英

为什么可以将右值间接绑定到左值引用,而不能直接绑定呢?

[英]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.

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