C++ 浅拷贝与深拷贝构造函数

#include <iostream>
#include <cstring>
using namespace std;

/*
    浅拷贝和深拷贝区别
    1.浅拷贝,若类中不存在拷贝构造函数,会提供默认拷贝构造函数(浅拷贝),可以进行对象值赋值;
	但当数据成员中存在需要在堆区申请空间时,析构时浅拷贝会造成空间双重释放问题;
	2.深拷贝,当数据成员中存在需要在堆区申请空间时,会调用深拷贝,重新申请新的空间,可以避免析构时堆区空间被多次释放问题;
*/

class Person{
public:
	Person(int age, char* str)
	{
		cout<<"person构造函数"<<endl;
		m_age = age;
		int len = strlen(str);
		m_pName = new char[len+1];
		strcpy(m_pName, str);

		cout<<"age:"<<m_age<<","<<"name:"<<m_pName<<endl;
	}
	~Person()
	{
		if (m_pName != NULL)
		{
            cout<<"Person析构函数"<<endl;
            std::cout<<m_pName<<std::endl;
			delete m_pName;
			m_pName = NULL;
		}
		
	}

private:
    int m_age;
	char *m_pName;
};

void test()
{
	char str[100]="zhangsan";
	Person per(20, str);
	Person per1(per);//使用小括号法进行拷贝, free(): double free detected in tcache 2
}
int main()
{
    test();

    return 0;
}

执行时,会报错,因为m_pName堆区空间被两次释放,浅拷贝时直接将per成员的m_age和m_pName值赋值给per1的成员,per和per1的m_pName指向同一个空间,对象生命周期接收时,先释放per1对象m_pName空间,再次释放per的m_pName空间,导致多次释放报错;
在这里插入图片描述

#include <iostream>
using namespace std;
class Person{
public:

	Person(int age, char* str)
	{
		cout<<"person构造函数"<<endl;
		m_age = age;
		int len = strlen(str);
		m_pName = new char[len+1];
		strcpy(m_pName, str);

		cout<<"age:"<<m_age<<","<<"name:"<<m_pName<<endl;
	}
	//深拷贝
    Person(const Person &per)
    {
        m_age = per.m_age;
		int len = strlen(per.m_pName);
		m_pName = new char[len+1];
		strcpy(m_pName, per.m_pName);
		cout<<"Person拷贝构造函数"<<endl;
    }
	
	~Person()
	{
		if (m_pName != NULL)
		{
			delete m_pName;
			m_pName = NULL;
		}
		cout<<"Person析构函数"<<endl;
	}
private:
    int m_age;
	char *m_pName;
};

void test()
{
	char str[100]="zhangsan";
	Person per(20, str);
	Person per1(per);//使用小括号法进行拷贝

}
int main()
{
    test();

    return 0;
}

正常释放空间,因为Person per1(per),会调用深拷贝构造函数,per1中的m_pName成员在堆区重新申请了空间,per和per1对象的m_pName都有各自的空间,析构时释放的也是自己的空间,不会造成多处释放或未释放问题;
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值