我编写了一个简单的C++类示例,其中包含1个非参数构造函数、1个参数构造函数、2个复制构造函数、1个赋值运算符和1个加号运算符。
class Complex {
protected:
float real, img;
public:
Complex () : real(0), img(0) {
cout << "Default constructor\n";
}
Complex (float a, float b) {
cout << "Param constructor" << a << " " << b << endl;
real = a;
img = b;
}
// 2 copy constructors
Complex( const Complex& other ) {
cout << "1st copy constructor " << other.real << " " << other.img << endl;
real = other.real;
img = other.img;
}
Complex( Complex& other ) {
cout << "2nd copy constructor " << other.real << " " << other.img << endl;
real = other.real;
img = other.img;
}
// assignment overloading operator
void operator= (const Complex& other) {
cout << "assignment operator " << other.real << " " << other.img << endl;
real = other.real;
img = other.img;
}
// plus overloading operator
Complex operator+ (const Complex& other) {
cout << "plus operator " << other.real << " " << other.img << endl;
float a = real + other.real;
float b = img + other.img;
return Complex(a, b);
}
float getReal () {
return real;
}
float getImg () {
return img;
}
};
我在main中使用了这个类,就像这样:
int main() {
Complex a(1,5);
Complex b(5,7);
Complex c = a+b; // Statement 1
system("pause");
return 0;
}
结果打印为:
Param constructor 1 5
Param constructor 5 7
plus operator 5 7
Param constructor 6 12
我认为必须在语句1中使用复制构造函数,但我真的不知道调用哪个构造函数。请告诉我是哪一个,为什么?非常感谢
发布于 2013-05-19 15:24:43
编译器省略了对复制构造函数的调用(实际上是两个调用)。这是允许的(但不是强制的!)根据C++11标准的第12.8/31段,即使构造函数或析构函数有副作用:
当满足某些条件时,允许实现省略类对象的复制/移动构造,,即使为复制/移动操作选择的构造函数和/或对象的析构函数具有副作用。。。这种拷贝/移动操作的省略,称为拷贝省略,在以下情况下是允许的(可以组合起来以消除多个拷贝):
-在具有类返回类型的函数中的return
语句中,当表达式是具有与函数返回类型相同的cv未限定类型的非易失性自动对象(函数或catch子句参数除外)的名称时,可以通过将自动对象直接构造到函数的返回值中来省略复制/移动操作
..。
-当尚未绑定到引用(12.2)的临时类对象将被复制/移动到具有相同的cv未限定类型的类对象时,可以通过将临时对象直接构造到被省略的复制/移动的目标中来省略复制/移动操作
如果编译器没有省略对复制构造函数的调用,那么第一个将被选中两次,即具有以下签名的那个:
Complex( const Complex& other )
原因是:
operator +
返回的值是从临时(Complex(a, b)
)复制初始化的,并且只有对const
的左值引用才能绑定到临时变量。如果operator +
是这样写的,事情就不一样了:复杂operator+ (常量复杂和其他){ // ...复数c(a,b);返回c;}
在这种情况下,将调用第二个复制构造函数,因为c
不是左值,而是一个左值,因此它可以绑定到对const
-qualified的左值引用。main()
中的c
是从右值复制构造的( operator +
返回的值也是临时的)。无论operator +
如何返回其Complex
对象,只要它是按值返回的,都是如此。因此,只要不执行复制省略,就会选择第一个复制构造函数。
如果您使用的是GCC,并想验证此行为,请尝试设置-fno-elide-constructors
编译标志(Clang也支持它,但3.2版有一个bug,我不知道它是否已修复)。
https://stackoverflow.com/questions/16636236
复制相似问题