一,拷贝构造函数
概念:在类的定义中,构造函数只是单纯将内置类型进行初始化,而拷贝构造函数是将整个类进行拷贝到另一个类中进行初始化。在定义拷贝构造函数时,只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
这里要说明的是,拷贝构造函数也是特殊的成员函数,其特征如下:
1,拷贝构造函数是构造函数的一个重载形式。
2,拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为形参相当于实参的临时拷贝,在拷贝中会触发另一个拷贝构造函数的调用,从而引发无穷递归调用。传引用的话只会将源对象的别名进行拷贝,不会进行整体拷贝,从而避免了这种问题。
class Date { public: Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } //Date(const Date d)// 错误写法: 编译报错,会引发无穷递归 Date(const Date& d)// 正确写法 { _year = d._year; _month = d._month; _day = d._day; } private: int _year; int _month; int _day; }; int main() { Date d1;//调用构造函数 Date d2(d1);//用类进行初始化,会调用拷贝构造函数 return 0; }
引发无穷递归的过程图
3,若未显式定义,编译器会生成默认的拷贝构造函数。默认的拷贝构造函数只会进行浅拷贝,或者值拷贝。(浅拷贝是指只拷贝对象的基本数据类型和引用地址,不会拷贝引用地址所指向的对象,即原对象中的数据所指向的空间将与拷贝后的对象的数据所指向的空间相同)。
这里要说明的是默认拷贝构造函数的处理对象不跟默认构造函数一样,但处理自定义类型的方式跟默认构造函数一样。默认拷贝构造函数会对自定义类型和内置类型都做处理,其中,内置类型成员完成浅拷贝,自定义类型成员将会调用这个成员的拷贝构造。
#include <iostream> using namespace std; class Time { public: Time() { _hour = 1; _minute = 1; _second = 1; } Time(const Time& t) { _hour = t._hour; _minute = t._minute; _second = t._second; cout << "Time对象的拷贝构造" << endl; } private: int _hour; int _minute; int _second; }; class Date { private: // 内置类型 int _year = 1970; int _month = 1; int _day = 1; // 自定义类型,将会调用此对象的拷贝构造 Time _t; }; int main() { Date d1; Date d2(d1); return 0; }
d1类运行的调试内部分析图(构造函数)
d2类运行的调试内部分析图(拷贝构造函数)
下面问题来了,既然有默认拷贝构造函数,我们需要不需要再定义拷贝构造函数呢?
C++拷贝构造函数和运算符重载--2 https://developer.aliyun.com/article/1424586?spm=a2c6h.13148508.setting.31.214f4f0emw3QR7