之前没有细想过两者的区别,今天对此进行简要记录,后续完善补充。
复制构造函数是在类对象被创建时调用的,但是赋值运算符是被已经存在的对象调用完成赋值操作。
复制构造函数只在对象实例化时才被调用,即在复制构造函数调用期间,这个对象处于未决状态(直到复制构造函数被成功调用),另外复制构造函数没有返回值。
赋值运算符则是在一个现存对象被赋予新的值时才被调用,并且它有返回值(可以返回类对象,也可以返回类对象引用)
举个例子:
class A { public: A() { cout<<"class create"<<endl; } A(const A &a) { cout<<"class copy"<<endl; } A &operator=(const A &a) { cout<<"override ="<<endl; return *this; } }; int main() { //1 A x; //2 A y(x); //3 A z; z = y; //4 A w = x; return 0; }
给出输出结果,再进行分析:
1:定义类对象x,调用构造函数,输出class create
2:将类对象x复制给y,y是一个待进行实例化的对象,这里调用复制构造函数,输出class copy
3:定义类对象z,调用构造函数,输出class create,然后将y复制给z,这里z已经是一个现存的对象,这里调用赋值运算符重载。输出override =
4:属于隐式类转换,调用复制构造函数实例化类对象w,输出class copy。一般情况下,抑制隐式转换,可以采用explicit关键字。
上述赋值运算符重载函数返回类型为引用,如果返回类型为对象即 A operator=(const A &a),则会由于生成一个临时对象作为返回值复制给z,从而调用复制构造函数,并在返回后调用析构函数删除临时对象。测试如下:
class A { public: A() { cout<<"class create"<<endl; } A(const A &a) { cout<<"class copy"<<endl; } A operator=(const A &a) //返回对象 { cout<<"override ="<<endl; return *this; } ~A() { cout<<"class delete"<<endl; } }; int main() { //1 A x; //2 A y(x); //3 A z; z = y; //返回临时对象复制给z,不是返回的对象y的引用。 //4 A w = x; return 0; }
结果如下: