文章目录
1、浅拷贝(Shallow Copy)
浅拷贝只复制对象的成员变量的值,如果对象中有指针,浅拷贝会复制指针的值(即地址)
,而不是指针指向的内容。因此,浅拷贝后,两个对象的指针成员会指向同一块内存。
问题:如果其中一个对象释放了这块内存,另一个对象的指针就会变成悬空指针(dangling pointer),访问它会导致未定义行为。
class ShallowCopy {
public:
int* data;
ShallowCopy(int value) {
data = new int(value);
}
~ShallowCopy() {
delete data;
}
};
int main() {
ShallowCopy obj1(10);
ShallowCopy obj2 = obj1; // 浅拷贝
// obj1和obj2的data指针指向同一块内存
*obj2.data = 20;
std::cout << *obj1.data << std::endl; // 输出20
// 当obj1和obj2析构时,会尝试释放同一块内存,导致程序崩溃
}
2、深拷贝(Deep Copy)
深拷贝不仅复制对象的成员变量,还会为指针成员分配新的内存,并复制指针指向的内容
。因此,深拷贝后,两个对象的指针成员指向不同的内存块。
class DeepCopy {
public:
int* data;
DeepCopy(int value) {
data = new int(value);
}
// 深拷贝构造函数
DeepCopy(const DeepCopy& other) {
data = new int(*other.data); // 分配新内存并复制内容
}
// 深拷贝赋值运算符
DeepCopy& operator=(const DeepCopy& other) {
if (this == &other) return *this; // 自赋值检查
delete data; // 释放原有内存
data = new int(*other.data); // 分配新内存并复制内容
return *this;
}
~DeepCopy() {
delete data;
}
};
int main() {
DeepCopy obj1(10);
DeepCopy obj2 = obj1; // 深拷贝
*obj2.data = 20;
std::cout << *obj1.data << std::endl; // 输出10
std::cout << *obj2.data << std::endl; // 输出20
// obj1和obj2的析构函数不会冲突
}
3.拷贝构造函数
1. 什么是拷贝构造函数?
拷贝构造函数是C++中的一种特殊构造函数,用于创建一个新对象,并用另一个同类型对象的值来初始化它
。它的主要作用是 复制对象。
拷贝构造函数的定义形式如下:
ClassName(const ClassName& other);
ClassName 是类的名称。
other 是要被复制的对象,通常以 const 引用传递。
2. 拷贝构造函数的调用时机
拷贝构造函数在以下情况下会被调用:
- 显式复制对象:
MyClass obj1;
MyClass obj2 = obj1; // 调用拷贝构造函数
- 函数传参(按值传递对象):
void func(MyClass obj); // 调用拷贝构造函数
MyClass obj1;
func(obj1); // 传递obj1时,会调用拷贝构造函数
3. 默认拷贝构造函数
如果你没有为类定义拷贝构造函数,C++编译器会自动生成一个 默认拷贝构造函数。默认拷贝构造函数会逐个复制对象的成员变量(浅拷贝)。
class MyClass {
public:
int value;
int* ptr;
MyClass(int v, int p) : value(v), ptr(new int(p)) {}
~MyClass() { delete ptr; }
};
int main() {
MyClass obj1(10, 20);
MyClass obj2 = obj1; // 默认拷贝构造函数(浅拷贝)
// obj1和obj2的ptr指向同一块内存
*obj2.ptr = 30;
std::cout << *obj1.ptr << std::endl; // 输出30
// obj1和obj2析构时,会重复释放ptr,导致程序崩溃
}
问题:
默认拷贝构造函数是浅拷贝,如果对象中有指针或动态分配的资源,会导致多个对象共享同一块内存。
析构时可能会重复释放内存,导致程序崩溃。
4. 自定义拷贝构造函数(深拷贝)
为了避免浅拷贝的问题,可以为类定义自定义的拷贝构造函数,实现 深拷贝。
class MyClass {
public:
int value;
int* ptr;
// 普通构造函数
MyClass(int v, int p) : value(v), ptr(new int(p)) {}
// 自定义拷贝构造函数(深拷贝)
MyClass(const MyClass& other) : value(other.value), ptr(new int(*other.ptr)) {}
// 析构函数
~MyClass() { delete ptr; }
};
int main() {
MyClass obj1(10, 20);
MyClass obj2 = obj1; // 调用自定义拷贝构造函数(深拷贝)
*obj2.ptr = 30;
std::cout << *obj1.ptr << std::endl; // 输出20,obj1的ptr未被修改
std::cout << *obj2.ptr << std::endl; // 输出30,obj2的ptr被修改
// obj1和obj2析构时,各自释放自己的内存,不会冲突
}