我有以下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");
}
运行代码时,我在&#34; START OF TEST&#34;之间得到以下输出。和&#34;测试结束&#34;输出:
构造函数:1
复制构造函数:10
复制构造函数:10
析构函数:10
析构函数:10
析构函数:1
构建了3个对象:1个使用整数1
,2个使用类A
的对象(i = 10)。
值得一提的是,当test
函数的参数const A &a
更改为A &a
(不是常量)时,程序无法编译,给出以下错误:
错误C2664:&#39;测试(A&amp;,A,A *)&#39; :无法转换参数1 &#39; INT&#39;到&#39; A&amp;&#39;
这种行为是如何解释的?
具体做法是:
为什么向1
发送整数test
会使A的参数构造函数A(int i)
正常工作(并且仅在使用const
时)?< / p>
为什么A&#39的复制构造函数A(const A&amp; o)工作两次? (调用test
时会发生一次运行,而返回*c
时会发生另一次运行。)
答案 0 :(得分:5)
好吧,使用第一个参数test
调用1
会导致创建类型为rvalue
的{{1}}。可以将右值分配给A
,但不能分配给普通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
= 5
然后您就可以修改int &r
。
另一方面,5
禁止对他们引用的对象进行任何更改,因此您可以将它们绑定到lvalue references to const
。
rvalue
关于第二个问题。您将从const A& x = 1; //compile
x = 2; //error!
A&& xxx = 1; //compile
A& xx = 1; //does not compile.
返回A
的副本,以便test
触发构建*c
的副本。
尝试从c
返回引用A
,以查看未调用构造函数。