C++拷贝构造函数详解
拷贝构造函数的作用
核心作用:通过同类型的已有对象来初始化新对象(成员变量的拷贝初始化)。
与普通构造函数的区别:
-
普通构造函数:从无到有初始化对象。
-
拷贝构造函数:从已有对象拷贝初始化。
拷贝构造函数的特性
1. 是构造函数的重载形式
-
函数名与类名相同,无返回值。
-
必须接受 同类对象的引用 作为参数(通常是
const
引用)。
2. 参数必须是引用(避免无限递归)
cpp
class MyClass { public:// 正确:参数是引用MyClass(const MyClass& other) { /*...*/ }// 错误:传值会导致无限递归调用拷贝构造MyClass(MyClass other) { /*...*/ } // 编译报错 };
原因:
传值方式会触发拷贝构造,而拷贝构造又需要传值→无限递归,最终栈溢出。
3. 编译器默认生成
-
若未显式定义,编译器会生成一个默认拷贝构造函数。
-
默认行为:
-
内置类型:按字节浅拷贝(直接赋值,包括指针变量)。
-
自定义类型成员:调用该成员的拷贝构造函数(递归处理)。
-
4. 调用时机
以下情况会调用拷贝构造函数:
-
用已有对象初始化新对象:
cpp
MyClass obj1; MyClass obj2(obj1); // 直接调用拷贝构造 MyClass obj3 = obj1; // 调用拷贝构造(不是赋值运算符!)
-
函数参数传递(按值传参时):
cpp
void func(MyClass obj); // 实参传递时会调用拷贝构造
-
函数返回对象(按值返回且未优化时):
cpp
MyClass createObj() {MyClass obj;return obj; // 可能调用拷贝构造(受RVO/NRVO优化影响) }
默认拷贝构造的潜在问题
当类中有指针成员时,默认浅拷贝会导致双重释放
解决方法:自定义拷贝构造函数实现深拷贝: