1.浅拷贝:
在进行对象拷贝时,浅拷贝只复制对象中的成员变量的值,而不复制指向动态分配内存的指针。这意味着原始对象和拷贝对象将共享相同的内存资源。但由于浅拷贝可能导致多个对象同时释放同一块内存,从而引发内存错误或程序崩溃等问题,因此其安全性较低;
例如:
Complex cp1(2.0,3.0);
1>Complex cp2=cp1; // 类对象初始化
2>Complex cp2(cp1); // 类对象初始化
这两种形式进行浅拷贝都可以;
2.深拷贝:
如果数据成员中包含指针,利用浅拷贝的形式进行拷贝,两个指针指向同一个地址,在析构函数中释放的时候,另一个指针变成了悬挂指针,指向一个已经被释放的内存地址,这会导致未定义的行为,包括程序崩溃等问题。
因此,我们引入深拷贝;
深拷贝不仅复制对象的成员变量的值,还会为新对象分配独立的内存空间并复制原始对象中的实际数据,这样两个对象就拥有各自独立的内存资源,不会相互影响。同时,深拷贝通过为每个对象分配独立的内存,这样也提高了安全性;
类中函数的声明:(只写了三个函数)
#include <iostream>
using namespace std;
class RandNumber{ // 类定义
public:
RandNumber(int n=5); // 构造函数
RandNumber(const RandNumber &rn); // 拷贝构造函数
~RandNumber(); // 析构函数
private:
int *vec; // 存放随机数
int num; // 随机数个数
};
类的成员函数实现:
RandNumber::RandNumber(int n): num(n) // 构造函数
{
vec = new int[num];
for(int i=0; i<num; i++)
vec[i] = rand()%100;
}
RandNumber::RandNumber(const RandNumber &rn) // 拷贝构造函数
{
num = rn.getNum();
vec = new int[num]; // 重新申请一个堆空间
for(int i=0; i<num; i++) // 依次值拷贝
vec[i] = rn.get(i);
}
RandNumber::~RandNumber() // 析构函数
{
if(vec!=NULL)
delete [ ] vec;
}
在拷贝构造函数中可以直接访问类的私有成员。
class Complex
{
public:
Complex(double r, double img): real(r), image(img) { }
Complex(const Complex &cp)
{
real = cp.real; image = cp.image; // 直接访问私有成员
}
~Complex() { }
private: // 私有数据成员
double real;
double image;
};
拷贝构造函数可以在初始化列表中进行复制,另外,初始化列表只能用于构造函数。
Complex(const Complex &cp): real(cp.real), image(cp.image) { }