C++中的深拷贝与浅拷贝

假设存在一个结构体

struct stu
{
	int i;
	char c;
	char* p;
};
int main()
{
	struct stu s1, s2;
	char str = "rabbit is cute";
	s1.i = 345;
	s1.c = 'y';
	s1.p = (char*)str;
	s2 = s1;
	printf("s2 %d, %c, %s\n", s2.i, s2.c, s1.p);
	printf("s1 ptr: %d, s2 ptr : %d\n", s1.p, s2.p);
}

产生的结果是这样的:

s2 345, y, rabbit is cute

s1 ptr: 7934, s2 ptr : 7934

可以看到的是S2 确实得到了S1 传递的值,但是第二句的话却说明这样的一个问题,其实S2和S1的指针p都指向一个内存地址,这又说明了什么?

这说明指针的并没有将内容复制一块给新指针来指向,只是让新指针指向原来的那个内存,这样就相当于,指针在这个复制的过程中只是复制了地址,而不是内容。

原理:​

在拷贝过程中,如果没有自定义拷贝构造函数,系统会提供一个缺省的拷贝构造函数,缺省的拷贝构造函数对于基本类型的成员变量,按字节复制,对于类类型成员变量,调用其相应类型的拷贝构造函数。但是注意缺省的构造函数却是这样的:缺省拷贝构造函数在拷贝过程中是按字节复制的,对于指针型成员变量只复制指针本身,而不复制指针所指向的目标–浅拷贝。

这就是产生问题的原因了,浅拷贝出现了。。。

用下图来解释这个问题:
在这里插入图片描述

在进行对象复制后,事实上s1、s2里的成员指针p都指向了一块内存空间(即内存空间共享了),在s1析构时,delete了成员指针p所指向的内存空间,而s2析构时同样指向(此时已变成野指针)并且要释放这片已经被s1析构函数释放的内存空间,这就让同样一片内存空间出现了“double free” ,从而出错。而浅拷贝还存在着一个问题,因为一片空间被两个不同的子对象共享了,只要其中的一个子对象改变了其中的值,那另一个对象的值也跟着改变了。

其实类的结构和上面的结构体是类似的,其实可以将结构体看成一个类来处理,结构体也可有自己的构造、析构、重载运算符河函数,可以简单的认为结构体是类的一种形式。

拷贝有两种:深拷贝,浅拷贝

当出现类的等号赋值时,会调用拷贝函数 在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的。 但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象。 所以,这时,必须采用深拷贝。 深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。 简而言之,当数据成员中有指针时,必须要用深拷贝。​

​建议:

我们在定义类或者结构体,这些结构的时候,最后都重写拷贝构造函数,避免浅拷贝这类不易发现但后果严重的错误产生。​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值