C++ 类和对象:拷贝构造与赋值运算符详解
在 C++ 面向对象编程中,对象的复制操作无处不在。无论是函数传参、返回值传递,还是对象间的赋值,都需要精确控制数据的复制行为。C++ 通过拷贝构造函数和赋值运算符重载两套机制,为开发者提供了对象复制的完整解决方案。
深入理解拷贝构造函数
如果一个构造函数的第一个参数是自身类型的引用,且其他所有参数都有默认值(如果有),就叫做拷贝构造,它是特殊的构造函数。
基本形式
#include <iostream>
using namespace std;
class Example {
public:
Example(Example& d) {
// ...
}
};
核心特点解析
- 重载规则:拷贝构造函数是构造函数的一个重载。
- 参数要求:第一个参数必须是自身类类型的引用(
类名&或const 类名&)。推荐使用const引用,既能避免修改原对象,又能防止因传值引发的无限递归调用。 - 多参数支持:可以有多个参数,但第一个必须为引用,其余必须有缺省值。
- 隐式调用:C++ 规定自定义类型对象进行拷贝行为必须调用拷贝构造。因此,自定义类型传值传参和传值返回都会触发此机制。
- 编译器生成:若未显式定义,编译器会生成默认的拷贝构造函数。对内置类型成员变量完成值拷贝(浅拷贝),对自定义类型成员变量则调用其拷贝构造。
- 深浅拷贝选择:如果类中有指针指向资源(如动态内存),编译器生成的浅拷贝会导致析构时重复释放同一块空间。此时必须显式定义深拷贝。
- 返回值陷阱:传值返回会产生临时对象调用拷贝构造;传引用返回虽减少拷贝,但若返回的是局部对象的别名,函数结束销毁后访问将导致野指针错误。
经验之谈:如果一个类显式实现了析构并释放资源,那么它通常需要显式定义深拷贝,否则可能埋下隐患。
调用时机
-
初始化新对象:用一个对象初始化另一个同类的对象。
Date a; Date b(a); // 调用拷贝构造 Date c = a; // 等价于 Date c(a),调用拷贝构造 -
函数传参:函数参数按值传递该类的对象。
void func(Date obj) { ... } Date a; func(a);


