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

浅拷贝问题抛出:

#define _CRT_SECURE_NO_WARNINGS
#include "iostream"
using namespace std;

/*
  浅拷贝问题抛出
*/
class ShallowCopy
{
public:
	ShallowCopy(const char * myp)
	{
		len = strlen(myp);
		p = (char *)malloc(len + 1); //指针指向谁,就把谁的地址给指针。把内存空间首地址给p,+1是\0,没有的话会内存越界。
		strcpy(p, myp);//把myp指针所指向的内存空间的数据copy到p所指向的内存空间。
	}
	
	~ShallowCopy()
	{
		if ( p != NULL )
		{
			free(p);
			p = NULL;
			len = 0;
		}
	}
private:
	char * p;
	int len;
};
void ObjPlaymain()
{
	ShallowCopy  obj1("abcdefg");
	/*
	   调用obj2类的copy构造函数,没写,调用c++编译器提供的copy构造函数(浅拷贝)
	   c++编译器偷懒,浅拷贝,把obj1的属性拷贝到obj2,只把指针变量的值拷贝过来了,没有另外开辟内存。
	   */
	ShallowCopy obj2 = obj1;
}
void main()
{
	ObjPlaymain();
	system("pause");
}

这样程序会出现coredump, 可以用如下内存图理解:
在这里插入图片描述
c++编译器默认的copy构造函数,浅拷贝,把obj1的属性拷贝到obj2,只把指针变量的值拷贝过来了,没有另外开辟内存。这样obj1和obj2的p指针指向同一块内存空间。
析构的时候,先析构obj2,把那块内存空间析构掉了,同时把内存空间置成NULL,把len置成0。然后析构obj1,此时那块内存空间是垃圾值(已经析构过了),则此时的obj1的指针p是个野指针,调用obj1的析构函数,同一块内存空间被析构了2次。析构的时候程序会出现coredump。
那怎么办呢?
蓝色箭头是我们的解决方案。既然c++编译器提供的copy构造函数不行,我们就手动编写copy构造函数呗,让2个指针不要指向同一块内存,给它重新开辟。所以必要的时候,必须手工编写copy构造函数。
下面是解决方案:

#define _CRT_SECURE_NO_WARNINGS
#include "iostream"
using namespace std;

/*
  浅拷贝问题解决:不使用c++编译器提供的copy构造函数,手工编写copy构造函数,使用深拷贝。
*/
class DeepCopy
{
public:
	DeepCopy(const char * myp)
	{
		len = strlen(myp);
		p = (char *)malloc(len + 1 ); 
		strcpy(p, myp);
	}

	DeepCopy(const DeepCopy & obj1)
	{
		len = strlen(obj1.p);
		p = (char *)malloc(len + 1);
		strcpy(p, obj1.p);
	}

	~DeepCopy()
	{
		if (p != NULL)
		{
			free(p);
			p = NULL;
			len = 0;
		}
	}
private:
	char * p;
	int len;
};
void ObjPlaymain()
{
	DeepCopy  obj1("abcdefg");
	DeepCopy obj2 = obj1;
}
void main()
{
	ObjPlaymain();
	system("pause");
}

这样就不会出现问题了,ok!

之前说过初始化和赋值不一样,如果用=连接obj1和obj2,又会怎样呢?

#define _CRT_SECURE_NO_WARNINGS
#include "iostream"
using namespace std;

/*
  =也不行,需要重载操作符
*/
class DeepCopy
{
public:
	DeepCopy(const char * myp)
	{
		len = strlen(myp);
		p = (char *)malloc(len + 1);
		strcpy(p, myp);
	}

	~DeepCopy()
	{
		if (p != NULL)
		{
			free(p);
			p = NULL;
			len = 0;
		}
	}
private:
	char * p;
	int len;
};
void ObjPlaymain()
{
	DeepCopy  obj1("abcdefg");
	DeepCopy obj2("obj2");
	/*
	  =操作,把obj1的属性copy给obj2,用c++默认的copy构造函数,
	  和刚才浅拷贝一样,析构时出现问题,需要重载操作符=
	*/
	obj2 = obj1;
}
void main()
{
	ObjPlaymain();
	system("pause");
}

结果发现,和刚才一样,也会出现同样的问题。
依旧用内存图解释:
在这里插入图片描述
人家obj1和obj2本来指向不同的内存空间,各不干扰。结果你"obj2=obj1"一下,把obj1的值赋值给obj2,obj2的p和len和obj1一模一样,把人家obj2的p指针活生生指到obj1那块内存空间了,结果造成obj1和obj2的指针又指向同一块内存空间了,析构的时候又出现coredump。而且,原来人家obj2的0xbb11那块内存被暴露出来了,内存泄露了。
这个"="也太肤浅了吧,看来需要操作符重载喽!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值