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

本文探讨了C++中的深拷贝与浅拷贝问题。当类对象在没有自定义拷贝构造函数和重载赋值运算符的情况下进行拷贝时,会发生浅拷贝,可能导致内存泄漏和系统崩溃。为解决此问题,文章介绍了深拷贝的概念,通过重新定义拷贝构造函数和重载=运算符,确保每个对象拥有独立的内存空间,防止资源误释放。结论强调在处理包含指针成员的类时,应谨慎处理拷贝行为,适时采用深拷贝策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

浅拷贝问题

当用一个类对象去初始化这个类的另一个对象时,如果这个类没有提供拷贝构造函数以及重载=运算符,这时就会发生浅拷贝。如下代码所示

class Name
{
public:
	Name(const char *pname)
	{
	     this->size=strlen(pname);
	     this->pName=(char *)malloc(size+1);
	     strcpy(this->pName,pname);
	}
	~Name()
	{
	     if(pName!=NULL)
	     {
	     	free(pName);
	     	pNmae=NULL;
	     	size=0;
	     }
	}
private:
	char *pName;
	int size;
}
void fun1()
{
	Name obj1("obj1");//初始化obj1
	Name obj2 = obj1;//用obj1去初始化obj2,这种情况会发生浅拷贝
}
void fun2()
{
	Name obj3("obj3");
 	obj3=obj1;//将obj1赋值给obj1 这种情况会发生浅拷贝
}
int main()
{
	fun1();
	fun2();
	return 0;
}

上述代码的内存图如图所示
在这里插入图片描述
在这里插入图片描述

  • 由此可知,在类中含有指针时,如果没有定义拷贝构造函数,系统会默认地对指针进行浅拷贝,即系统默认的拷贝构造函数并不会为 obj2pName指针申请新的内存空间,而是直接将指针指向obj1pName的内存空间。
    这样就会带来严重的问题:当obj2被析构时,obj2 pName所指向的内存空间就会被释放掉,当析构obj1 pName所指向的内存空间时,发现内存空间早已被obj2的指针给释放掉,这时就会引发系统崩溃。

  • 如果未重载=运算符,obj3=obj1 也会引发类似的问题

浅拷贝解决方法

· 深拷贝
为了防止由浅拷贝所带来的同一内存空间的多次释放,需要重新定义拷贝构造函数以及重载=操作符,为新对象初始化及进行赋值操作时额外申请内存空间,进行深拷贝

代码如下所示

class Name
{
public:
	 Name(const char *pname)
	 {
     	 	this->size=strlen(pname);
     	 	this->pName=(char *)malloc(size+1);
     	 	strcpy(this->pName,pname);
 	}
 	Name(Name &obj)//定义拷贝构造函数
 	{
 		this->size=obj.size;
 		this->pName=(char *)malloc(size+1);
 		strcpy(this->pName,obj.pName);
 	}
 	//重载=操作符
 	Name& operator=(Name &obj)
 	{
 		if(pName!=NULL)
 		{
 			free(pName);
 			pName=NULL;
 			size=0;
 		}
 		this->size=obj.size;
   		this->pName=(char *)malloc(size+1);
   		strcpy(this->pName,obj.pName);
		return *this;
 	}
 	~Name()
 	{
      		if(pName!=NULL)
      		{
       			free(pName);
       			pNmae=NULL;
       			size=0;
      		}
 	}
private:
 	char *pName;
	int size;
}

内存图为
在这里插入图片描述
在这里插入图片描述
有了各自的内存空后,就不会出现同一内存空间被释放两次的情况

结论

当类中有指针成员时,需要注意指针的内存空间的使用情况,避免发生浅拷贝,必要时进行深拷贝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值