一、概念
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型 对象创建新对象时由编译器自动调用。
二、特征
拷贝构造函数也是特殊的成员函数,其特征如下:
1. 拷贝构造函数是构造函数的一个重载形式。
2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
下面用代码解释一下:
class Data
{
public:
Data(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// Data(Data d) // 不加 & 的话 会出现循环拷贝
// Data(Data& d) // 不加 const 的话,如果写成 d._year = _year 那么原本的值就会被随机值覆盖!所以用引用(&)就要加 const
Data(const Data& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
private:
int _year = 1;
int _month = 1;
int _day = 1;
};
void fun()
{
Data d1(2022, 11, 1);
Data d2(d1);
}
int main()
{
fun();
return 0;
}
下面是引发无穷递归调用的示例:
3. 若未显式定义,编译器会生成默认的拷贝构造函数,默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
注意:在编译器生成得到默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用其拷贝构造函数完成拷贝的。
下面用上面的代码屏蔽掉显示写的拷贝构造函数,在进行调试发现执行 Date d2(d1) 这句的时候,用已经存在的 d1 拷贝构造d2,此处会调用Date类的拷贝构造函数。
注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构 造函数是一定要写的,否则就是浅拷贝。
4. 拷贝构造函数典型调用场景:
①使用已存在对象创建新对象 ②函数参数类型为类类型对象 ③函数返回值类型为类类型对象