将右值绑定到左值引用
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
发送到 test
会使 A 的参数构造函数 A(int i)
起作用(并且仅当使用 const
时)?
为什么A的拷贝构造函数A(const A &o)执行了两次? (一个 运行 在调用 test
时发生,另一个在返回 *c
时发生。
好吧,使用第一个参数 1
调用 test
会导致创建类型 A
的 rvalue
。右值可以分配给 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 reference
或 lvalue 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
以查看未调用构造函数。
我有以下 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
发送到test
会使 A 的参数构造函数A(int i)
起作用(并且仅当使用const
时)?为什么A的拷贝构造函数A(const A &o)执行了两次? (一个 运行 在调用
test
时发生,另一个在返回*c
时发生。
好吧,使用第一个参数 1
调用 test
会导致创建类型 A
的 rvalue
。右值可以分配给 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 reference
或 lvalue 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
以查看未调用构造函数。