将右值绑定到左值引用

Binding rvalue to lvalue reference

我有以下 C++ 代码 (VS2013):

#include <iostream>
using namespace std;

class A {
    int i;
public:
    A(int i) : i(i) {
        cout << "Constructor: " << i << endl;
    }
    A(const A &o) : i(o.i) {
        cout << "Copy constructor: " << i << endl;
    }
    ~A() {
        cout << "Destructor: " << i << endl;
    }
};

A test(const A &a, A b, A *c) {
    return *c;
}

int main() {
    A b(10);
    cout << "START OF TEST" << endl;
    test(1, b, &b);
    cout << "END OF TEST" << endl;
    system("pause");
}

当 运行 运行代码时,我在 "START OF TEST" 和 "END OF TEST" 输出之间得到以下输出:

Constructor: 1

Copy constructor: 10

Copy constructor: 10

Destructor: 10

Destructor: 10

Destructor: 1

构建了 3 个对象:1 个使用整数 1,2 个使用 class A 的对象(i = 10)。

值得一提的是,当test函数的参数const A &a改为A &a(不是常量)时,程序编译不通过,报如下错误:

Error C2664: 'A test(A &,A,A *)' : cannot convert argument 1 from 'int' to 'A &'

如何解释这种行为?

具体来说:

  1. 为什么将整数 1 发送到 test 会使 A 的参数构造函数 A(int i) 起作用(并且仅当使用 const 时)?

  2. 为什么A的拷贝构造函数A(const A &o)执行了两次? (一个 运行 在调用 test 时发生,另一个在返回 *c 时发生。

好吧,使用第一个参数 1 调用 test 会导致创建类型 Arvalue。右值可以分配给 const lvalue reference 但不能分配给普通的 lvalue 引用。如果你想让它在不使用 const 的情况下编译,你必须指定参数是一个 rvalue 引用。

g++ 错误提供了更多信息:

 error: cannot bind non-const lvalue reference of type ‘A&’ to an rvalue of type ‘A’
     test(A(1), b, &b);

rvalue 可以分配给 rvalue referencelvalue reference to const

  • 这是为什么? rvalues 是临时对象或文字。如果此代码合法

    int &r = 5

    那么你就可以修改5了。 另一方面 lvalue references to const 禁止对它们引用的对象进行任何更改,因此您可以将它们绑定到 rvalue.


const A& x = 1; //compile
x = 2;         //error!
A&& xxx = 1; //compile
A& xx  = 1; //does not compile.

关于第二个问题。您正在从 test 返回 A 的副本,因此 *c 触发构建 c 的副本。 尝试从 test 返回引用 A 以查看未调用构造函数。