拷贝构造函数
构造函数参数引用类型的是拷贝函数,加了const进行修饰,避免修改实参,引用避免无限递归
ClassName(const ClassName &other);
作用
对象初始化:拷贝构造函数在新对象被创建时,被用于初始化它,使其成为现有对象的副本。
调用时机
1.拷贝构造函数是通过已经存在的对象初始化新对象
2.函数的参数以值的形式传递时 (参数或返回值以值的方式传递的时候)
3.返回值以值的方式返回时(右值)
分类
浅拷贝:简单的赋值拷贝操作
深拷贝:在类中利用指针或动态内存时,拷贝构造函数被用来实现深拷贝,从而避免因直接复制指针而导致的双重释放同一内存的问题。
class MyClass {
private: int* data;
public: // 构造函数 MyClass(int value) { data = new int(value); // 动态分配内存 } // 拷贝构造函数 MyClass(const MyClass &other) { data = new int(*other.data); // 深拷贝 } // 析构函数 ~MyClass() { delete data; // 释放内存 }
}; int main() { MyClass obj1(10); // 使用构造函数 MyClass obj2 = obj1; // 使用拷贝构造函数 return 0;
}
赋值运算符重载
赋值运算符重载是用来定义对象赋值操作行为的特殊成员函数,其形式通常为:
ClassName& operator=(const ClassName &other);
调用时机
1. 使用一个对象给另一个已经存在的对象赋值。
2.通过赋值初始化方式初始化一个对象。
作用
对象赋值:赋值运算符重载允许我们定义对象在赋值语句中(例如 a = b;
)的行为,尤其当类包含动态分配的资源时。
避免内存泄漏:重载赋值运算符可以实现深拷贝,以防止内存泄漏和双重释放的问题,确保正确管理内存。
class MyClass {
private: int* data;
public: // 构造函数 MyClass(int value) { data = new int(value); // 动态分配内存 } // 拷贝构造函数 MyClass(const MyClass &other) { data = new int(*other.data); // 深拷贝 } // 赋值运算符重载 MyClass& operator=(const MyClass &other) { if (this != &other) { // 自我赋值检查 delete data; // 释放旧内存 data = new int(*other.data); // 深拷贝 } return *this; // 返回当前对象的引用 } // 析构函数 ~MyClass() { delete data; // 释放内存 }
}; int main() { MyClass obj1(10); // 使用构造函数 MyClass obj2(20); // 使用构造函数 obj2 = obj1; // 调用赋值运算符重载 return 0;
}
总结
拷贝构造函数:用于初始化新对象,使其成为现有对象的副本,防止共享同一内存地址。
赋值运算符重载:用于定义对象赋值的行为,确保正确处理动态资源,避免内存泄漏和错误的内存访问。
区别
调用时机:
拷贝构造函数在对象创建时调用,用于初始化新对象。
赋值运算符重载在对象已经存在时调用,用于将一个对象的值赋给另一个已经存在的对象。
参数类型不同:
拷贝构造函数的参数是一个对象的引用,用于初始化新对象。
赋值运算符重载的参数是一个对象的引用,用于赋值给另一个已经存在的对象。
返回值类型不同:
拷贝构造函数没有返回值,因为它的作用是初始化对象,不需要返回任何值。
赋值运算符重载返回一个引用,通常返回 *this,以支持连续赋值操作。