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

Why can you indirectly bind an rvalue to an lvalue reference but not directly?

本文关键字:绑定 引用 不能 为什么      更新时间:2023-10-16

根据我所读到的内容,您无法将右值表达式绑定到左值引用。然而,我看到的是,你可以将右值绑定到右值引用,因为命名的右值引用本质上是一个左值,所以你可以将它绑定到左值引用。不允许将右值绑定到左值引用的原因是什么。它是否用于优化目的?

举个例子:

#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引用"(一组类型;不要与实际的右值混淆)至少在一定程度上是创建的,这样,如果您真的想这样做,仍然可以

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

这些后来的规则比最初的基本规则来得晚得多,在过去的二十年里,基本规则无疑防止了许多错误。

请注意,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通过,因此生成一个临时的intss的值初始化。因此incr()修改了临时结果没有反映回调用函数。

我强烈推荐《C++的设计与进化》,因为它可以理解许多"为什么会有问题",尤其是关于C++98标准之前制定的规则。这是一部内容丰富、引人入胜的语言史。

当您调用foo(1)时,会创建一个等于1的临时int,并将其绑定到int&& a。您可以自由更改它。与编写int&& a = 1;的方法相同。a本身是一个左值,因此您可以将左值引用绑定到它

你可能会读到Scott Meyers的一篇伟大的文章《通用参考》,其中详细解释了右值和左值参考。