深拷贝和浅拷贝

当一个类创建后,编译器就我们默认提供了三个函数

前提是自己没写这三个函数哈,比如用户定义了有参构造函数,编译器就不会在默认提供无参构造,若定义了拷贝构造函数,编译器将不在提供任何函数

构造函数无参,函数体为空
析构函数无参,函数体为空
拷贝构造函数对属性进行值拷贝

浅拷贝会带来堆区内存重复释放

举个例子:

#include<iostream>
using namespace std;
class Person {
public:
	int m_age;
	int *m_height;   //我们定义一个指针,为它分配内存(让它在堆区存储)
 
  //构造函数,因为我们设置了两个成员,所以我们自己重新定义下构造函数,有可控性
	Person(int age,int height) { 
		m_height = new int(height);
		m_age = age;
		cout << "person的有参构造函数" << endl;
	}

	Person(const Person &p) {  //拷贝函数
//编译器默认提供的拷贝函数就是简单的赋值操作,即浅拷贝就是编译器提供的默认构造函数)
		m_age = p.m_age;
		m_height = p.m_height;  
		cout << "Person的拷贝函数" << endl;
	}

	~Person() {
		//堆区开辟的内存在执行结束后,需要手动释放
		if (m_height != NULL) {
			delete m_height;
			m_height = NULL;
		}
		cout << "Person的析构函数" << endl;
	}
};
void test01() {
	Person p1(18,160);
	cout <<"年龄 "<< p1.m_age<<"身高 " <<*p1.m_height<< endl;
	Person p2(p1);
	cout << "年龄 " << p2.m_age << "身高 " << *p2.m_height << endl;
}
int main() {
	test01();
}

上面代码存在问题:拷贝函数(浅拷贝)就是单纯的赋值操作,在赋值p1.m_height指针时其时是地址拷贝给了p2.height,后p2执行析构函数时,把地址释放了,最后p1再来执行析构函数,但它的地址还是原来的地址(已经被p2被释放了),所以浅拷贝导致堆区内存重复释放

有些人可能会问:在析构函数那里不是判断了一下,为空不是不执行吗,会啥还会导致内存重复释放嘞?

可以这样理解:p2把指针指向的内存释放了,但p1里面的指针还是指向原来的地址,但是地址引进被释放了,所以就崩了;或者理解成p1与p2里的m_height其实是不一样的

此时引出深拷贝,在堆区重新开辟一段内存,让p1和p2两个指针指向的地址不一样,但值是一样的,结束后各种释放自己的内存,互不冲突

#include<iostream>
using namespace std;
class Person {
public:
	int m_age;
	int *m_height;   //我们定义一个指针,为它分配内存(让它在堆区存储)
 
  //构造函数,因为我们设置了两个成员,所以我们自己重新定义下构造函数,有可控性
	Person(int age,int height) { 
		m_height = new int(height);
		m_age = age;
		cout << "person的有参构造函数" << endl;
	}

	Person(const Person &p) {  //拷贝函数
//编译器默认提供的拷贝函数就是简单的赋值操作,即浅拷贝就是编译器提供的默认构造函数)
		m_age = p.m_age;
     
		//m_height = p.m_height;    这是默认拷贝函数(浅拷贝)


        m_height = new int(*p.m_height);  //深拷贝,就是重新在堆区申请内存




		cout << "Person的拷贝函数" << endl;
	}

	~Person() {
		//堆区开辟的内存在执行结束后,需要手动释放
		if (m_height != NULL) {
			delete m_height;
			m_height = NULL;
		}
		cout << "Person的析构函数" << endl;
	}
};
void test01() {
	Person p1(18,160);
	cout <<"年龄 "<< p1.m_age<<"身高 " <<*p1.m_height<< endl;
	Person p2(p1);
	cout << "年龄 " << p2.m_age << "身高 " << *p2.m_height << endl;
}
int main() {
	test01();
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值