深拷贝和浅拷贝是对象复制中的两个重要概念,特别是在处理动态内存分配时,这两个概念尤为重要。
一、浅拷贝(Shallow Copy)
浅拷贝是对象复制的一种方式,它只复制对象的所有成员变量的值。如果对象包含指针或动态分配的内存,浅拷贝只复制指针的值(即地址),而不复制指针所指向的实际内容。这意味着两个对象共享同一块内存区域,修改其中一个对象的数据会影响另一个对象。
#include <iostream>
using namespace std;
class Shallow {
public:
Shallow(int size) : size(size) {
data = new int[size]; // 动态分配内存
for (int i = 0; i < size; ++i) {
data[i] = i;
}
}
// 拷贝构造函数:执行浅拷贝(使用成员初始化列表)
Shallow(const Shallow& source) : size(source.size), data(source.data) {
cout << "Shallow Copy Constructor Called" << endl;
}
//析构函数释放开辟的动态空间
// ~Shallow() {
// delete[] data; // 释放内存
// cout << "Destructor Called" << endl;
// }
void display() const {
for (int i = 0; i < size; ++i) {
cout << data[i] << " ";
}
cout << endl;
}
void setDate(){
this->data[0] = 9;
}
private:
int* data;
int size;
};
int main() {
Shallow obj1(5);
Shallow obj2 = obj1; // 调用浅拷贝构造函数
obj1.display();
obj2.display();
cout << "对obj进行数据更改" << endl;
obj2.setDate();
obj1.display();
obj2.display();
}
在这个例子中,obj2 是通过浅拷贝构造函数从 obj1 创建的,因此 obj1 和 obj2 共享同一块内存。修改一个对象的数据会影响另一个对象。
二、深拷贝(Deep Copy)
深拷贝是对象复制的另一种方式,它不仅复制对象的所有成员变量的值,还会为指针或动态分配的内存分配新的内存空间,并复制指针所指向的实际内容。这意味着两个对象拥有独立的内存区域,修改其中一个对象的数据不会影响另一个对象。
#include <iostream>
using namespace std;
class Deep {
public:
Deep(int size) : size(size) {
data = new int[size]; // 动态分配内存
for (int i = 0; i < size; ++i) {
data[i] = i;
}
}
// 拷贝构造函数:执行深拷贝
Deep(const Deep& source) : size(source.size) {
data = new int[source.size];
for (int i = 0; i < size; ++i) {
data[i] = source.data[i];
}
cout << "Deep Copy Constructor Called" << endl;
}
~Deep() {
delete[] data; // 释放内存
cout << "Destructor Called" << endl;
}
void display() const {
for (int i = 0; i < size; ++i) {
cout << data[i] << " ";
}
cout << endl;
}
void setDate(){
this->data[0] = 9;
}
private:
int* data;
int size;
};
int main() {
Deep obj1(5);
Deep obj2 = obj1; // 调用浅拷贝构造函数
obj1.display();
obj2.display();
cout << "对obj进行数据更改" << endl;
obj2.setDate();
obj1.display();
obj2.display();
}
在这个例子中,obj2 是通过深拷贝构造函数从 obj1 创建的,因此 obj1 和 obj2 拥有独立的内存。修改一个对象的数据不会影响另一个对象。
三、深拷贝和浅拷贝的比较
- 浅拷贝:
只复制指针的值(地址),不复制指针所指向的实际内容。
对象共享同一块内存,修改一个对象的数据会影响另一个对象。
更快但风险更高,特别是在对象生命周期不同步的情况下。 - 深拷贝:
复制指针所指向的实际内容,分配新的内存空间。
对象拥有独立的内存,修改一个对象的数据不会影响另一个对象。
比浅拷贝更安全,但需要更多的时间和内存。
何时使用深拷贝和浅拷贝
- 浅拷贝适用于对象之间不共享动态内存的情况,或当你确定对象的生命周期是同步的。
- 深拷贝适用于对象之间需要独立管理动态内存的情况,避免共享内存带来的潜在问题。
四、其他注意事项
- 是实行浅拷贝时,因为对象之间共享动态内存,因此注意在执行析构函数时,造成一块动态内存的两次释放,造成程序错误。如浅拷贝部分代码的析构函数如果不注释就会造成空间的重复释放。
- 对于列表成员初始化不熟悉的可以看这篇文章:列表成员初始化。