C++(7)——浅拷贝与深拷贝

浅拷贝

浅拷贝主要是指:位拷贝,拷贝构造函数,赋值重载
浅拷贝会把指针变量的地址复制,多个对象共用同一块资源,同一块资源释放多次,崩溃或者内存泄漏。
具体请看下面的例子:

#define SEQ_INIT_SIZE 10
#define SEQ_INC_SIZE 2

class SeqList
{
	int *data;
	int maxsize;
	int cursize;
public:
	SeqList() :data(NULL),maxsize(SEQ_INIT_SIZE), cursize(0)	
	{
		data = (int*)malloc(sizeof(int) * maxsize);
	}
	~SeqList()
	{
		free(data);
		data = NULL;
	}
	SeqList & operator=(const SeqList & x)
	{
		if (this != &x)
		{
			data = x.data;
			maxsize = x.maxsize;
			cursize = x.cursize;
		}
		return *this;
	}
	SeqList(const SeqList& y):data(y.data),maxsize (y.maxsize),cursize(y.cursize){}
};
int main()
{
	SeqList seqa;
	SeqList seqb(seqa);
}

此时程序会崩溃,原因是:
在完成拷贝构造后,两个对象的data域都指向了同一块堆区空间,随着函数执行结束,seqb会调动自身的析构函数,释放资源,并回收空间,此时seqa调动自身的析构函数时,data域已经指向了一块失效空间,并进行了二次释放,程序崩溃。

int main()
{
	SeqList seqa;
	SeqList seqb;

	seqb = seqa;
}

此时程序依然会崩溃,原因有二:

  1. 调动构造函数后各自的data域指向各自的堆区空间,然后完成赋值后,seqbdata域转而指向seqadata域所指向的堆区空间,会造成二次释放。
  2. 同时,由于未对seqbdata域所指向的内存空间进行管理,造成了内存泄漏。

问题:那么什么时候,我们需要自己重写赋值语句和拷贝构造函数呢?

凡是在类设计的过程中,设计出指针或者设计出指向内核态的对象时,都必须重写自己的拷贝构造和赋值语句,比如文件句柄指针,线程id号信号量,互斥量,不允许这两种操作时,加上=delete即可。

因此,在我们了解了对象在内存中的分布情况后,我们就有了更加深刻的领悟,也就有了如下的深拷贝的方案。

深拷贝

深拷贝会重新开辟内存空间,每个对象共同拥有自己的资源。

SeqList & operator=(const SeqList & x)
	{
		if (this != &x)
		{
			free(data);//释放原有空间
			data = (int*)malloc(sizeof(int) * x.maxsize);
			memcpy(data, x.data, sizeof(int) * x.cursize);
			maxsize = x.maxsize;
			cursize = x.cursize;
		}
		return *this;
	}
	SeqList(const SeqList& y):maxsize (y.maxsize),cursize(y.cursize)
	{
		data = (int*)malloc(sizeof(int) * y.maxsize);
		memcpy(data, y.data, sizeof(int) * y.cursize);
	}
};

采用深拷贝方案后,修改代码如下:此时各自的堆区空间都得到了合法的使用和销毁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值