概念
拷贝构造函数只有一个参数,且该形参是对本类类型对象的引用(一般用const修饰)。该函数是用已经存在的对象创建新的对象,该函数由编译器自动调用
特征
拷贝构造函数是构造函数的重载,是一个特殊的构造函数;拷贝构造函数的参数只有一个且必须是类类型对象的引用,如果使用传值的方式进行调用,编译器会直接报错,这会引发无穷递归调用;如果未显示定义,编译器会生成默认的拷贝构造函数,但生成的拷贝构造函数是浅拷贝或者叫值拷贝(如果类中没有涉及到资源申请时,拷贝构造函数可以不用写)。
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
//Date(const Date d)
//{
// _year = d._year;
// _month = d._month;
// _day = d._day;
//}
Date(const Date& d)//与构造函数构成重载
{
_year = d._year;
_month = d._month;
_day = d._day;
}
void Print()
{
cout << _year << "年" << _month << "月" << _day << "日" << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d(2025, 7, 31);
Date d1 = d;
Date d2(d);
d1.Print();
d2.Print();
return 0;
}
当拷贝构造采用传值拷贝时,报错如图:
当用默认的拷贝构造函数拷贝栈类时,代码:
class Stack
{
public:
Stack(int capacity = 4)
{
_a = (int*)malloc(sizeof(int) * capacity);
_size = 0;
_capacity = 0;
}
//Stack(const Stack& st)//显示定义拷贝构造函数
//{
// _a = (int*)malloc(sizeof(int) * st._capacity);
// _size = st._size;
// _capacity = st._capacity;
// memcpy(_a, st._a, sizeof(int) * _capacity);
//}
~Stack()
{
free(_a);
_size = _capacity = 0;
}
private:
int* _a;
int _size;
int _capacity;
};
int main()
{
Stack st;
Stack st1 = st;
return 0;
}
当未显示定义构造函数时,通过调试可以发现拷贝构造仅发生了值拷贝,如图:
这样会导致st和st1的_a指向同一块空间,这会导致调用析构函数时会对用一块空间重复释放,编译器报错。因此为了避免这一结果,必须要显示定义拷贝构造函数。