拷贝构造
拷贝构造的定义
拷贝构造是一种特殊的构造函数,它显式的第一个参数是本类类型的引用,如果还有其他参数的话,其他参数必须有默认值(一般情况没有其他参数,只有类类型引用)
例:
class Date
{
public:
//默认构造函数
Date(int year = 0, int month = 0, int day = 0)
:_year(year)
,_month(month)
,_day(day)
{}
//拷贝构造,参数只有本类型引用
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
//赋值运算符重载,稍后会讲
Date& operator=(const Date& d);
void Print()
{
cout << _year << "年" << _month << "月" << _day << "日" << endl;
}
private:
int _year;
int _month;
int _day;
};
Date& Date::operator=(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this;
}
拷贝构造的特点
- 拷贝构造是构造函数的重载
- 拷贝构造的参数一般只有本类型引用(如果有其他参数则必须给予默认值),如果不是引用而是传值传参则会引发无穷递归,因为传值传参中,形参是实参的临时拷贝,这就需要用到拷贝构造,这样就会导致拷贝构造的形参又要调用拷贝构造,从而引发无穷递归
- 如果没有显式定义拷贝构造,编译器会默认生成一个拷贝构造,默认生成的拷贝构造只会完成内置类型的浅拷贝,对于自定义类型则会调用该自定义类型的拷贝构造
- 拷贝构造在自定义类型的传值传参以及用自定义类型作为函数返回值时使用较多,因为这都需要进行拷贝,也就需要拷贝构造
赋值重载
赋值重载的定义
赋值重载是一个运算符重载函数,是一个默认的成员函数,用于两个已经存在的对象的拷贝赋值,这里需要与拷贝构造相区分,拷贝构造是用一个对象去拷贝另外一个正在创建的对象
例:
//这里采用的Date类即为上例中Date类
int main()
{
Date d1(2024,7,15);
Date d2;
d2 = d1;//这里d1与d2两个对象都已经创建好,已经存在了,是将d1的值拷贝给d2
//注意下面d3与d4都是拷贝构造,特别注意对于d4,它不是赋值重载而是直接使用d2的值来拷贝构造d4
Date d3(d1);
Date d4 = d2;
d1.Print();
d2.Print();
d3.Print();
d4.Print();
return 0;
}
输出结果如下:
赋值重载的特点
- 赋值运算符重载规定必须重载为成员函数,参数建议写成const 当前类类型引用以减少拷贝提高效率
- 有返回值,且返回值建议写成当前类类型引用以减少拷贝提高效率,这是为了支持连续赋值场景
- 没有显式重载赋值运算符时,编译器会默认生成一个,默认生成的重载成员函数会完成对内置类型的浅拷贝,对于自定义类型则会调用其拷贝构造