C++ 类和对象:拷贝构造与赋值运算符重载详解
在 C++ 面向对象编程中,对象的复制操作无处不在。无论是函数传参、返回值传递,还是对象间的赋值,都需要精确控制数据的复制行为。C++ 通过拷贝构造函数和赋值运算符重载两套机制,为开发者提供了对象复制的完整解决方案。
一、拷贝构造函数
如果一个构造函数的第一个参数是自身类型的引用,且 其他所有参数都有默认值(如果有) ,就叫做 拷贝构造,它是特殊的构造函数。
1.1 解析:拷贝构造特点
- 拷贝构造函数是构造函数的一个重载;
- 拷贝构造函数的第一个参数必须是自身类类型的引用:
类名&或const 类名&(建议加const)。如果使用传值的方式,逻辑上会引发无穷递归调用; - 拷贝构造函数可以有多个参数,第一个为引用,其他必须有缺省值;
- C++ 规定自定义类型对象进行拷贝行为必须调用拷贝构造,所以这里自定义类型传值传参和传值返回都会调用拷贝构造完成;
- 若未显式定义拷贝构造,编译器会生成自动生成拷贝构造函数。默认生成的拷贝构造对内置类型成员变量会完成值拷贝/浅拷贝,对自定义类型成员变量会调用它的拷贝构造;
- 类似
Date类,成员变量全是内置类型且不指向资源,编译器默认生成的拷贝构造就够了。类似Stack类,虽然也都是内置类型,但是指针指向资源,那么编译器默认生成的浅拷贝就不太够,需要显式定义深拷贝。再对于MyQueue类,自定义类型Stack变量成员就直接调用它的拷贝构造。
技巧:如果一个类显式实现了析构并释放资源,那么他就需要显式定义深拷贝,否则就不需要。
- 传值返回会产生一个临时对象来调用拷贝构造;而传引用返回,返回的是对象的别名,不会产生拷贝,但是返回的对象为一个当前函数局部域的局部对象,函数结束就会销毁,这时传引用返回是有问题的,类似于野指针。 (传引用返回会减少拷贝,但是要确保返回对象在函数结束时不会被销毁)
解释特点第 2 条: 当拷贝构造函数传值传参时,函数的形参是实参拷贝出来的新对象,要调用拷贝构造,但是拷贝构造函数也是传值传参就又要调用拷贝构造,这样无限循环下去……
其次,在引用传参最好加上 const,因为将对象传过来,也不会将对象进行改变操作,那么 const 就方便了传参(权限缩小)。当然,这时候传 const 对象也是可以的(权限平移)。
- 特点第 2 条拓展:既然要引用传参,那么指针可以吗? 先说,传指针是可以的,但是函数就变成普通的构造函数,不是拷贝构造函数。
#include <iostream>
using namespace std;
// 传指针
class Date {
public:
// 构造函数:全缺省
Date(int day = 8, int month = 1, int year = 2026) { _day = day; _month = month; _year = year; }
(Date* d) { _day = d->_day; _month = d->_month; _year = d->_year; }
{ cout << _year << << _month << << _day << endl; }
:
_day;
_month;
_year;
};
{
Date d1;
d();
;
d();
;
}


