C++之构造函数(2)深拷贝和浅拷贝

本文探讨了C++中的浅拷贝和深拷贝概念,特别是在类对象包含堆区分配内存时的重要性。通过示例代码解释了默认拷贝构造函数导致的问题,即浅拷贝在释放内存时可能引发重复释放,导致程序崩溃。解决办法是自定义深拷贝构造函数,确保每个副本拥有独立的堆内存,从而避免此类问题。强调了在类设计中,当属性涉及堆区开辟时,提供深拷贝构造函数的必要性。
摘要由CSDN通过智能技术生成

浅拷贝和深拷贝,在属性有堆区开辟,一定要自己提供拷贝构造函数。

重点看程序注释!

#include <iostream>
#include<string>

using namespace std;


class Person {
public:
	
	Person() {
		cout << "无参构造函数!" << endl;
	}
	//有参构造函数
	Person(int a) {
		age = a;
		cout << "有参构造函数!" << endl;
	}
	Person(int a,int h) {
		age = a;
		height = new int(h);//因为我在属性那建立了一个指针,指针只能接受地址,所以我传过来的h,通过开辟堆区空间
		//运算的结果是一个地址,所以用指针来接收,你如果不在程序中释放空间,这个程序一定能跑,但是,当你释放空间
		//的时候,要注意释放的时机。
		cout << "两参数的有参构造函数!" << endl;
	}
	//拷贝构造函数(先跳到59行看)
	Person(const Person& p) {
		age = p.age;
		//height = p.height;//可以看做是编译器出来的默认拷贝,但是刚也说了,要实现深拷贝,你现在这个只是浅拷贝
		height = new int(*p.height);//要注意是解引用,因为我是重新把你的值找一个地址的
		cout << "深拷贝构造函数!" << endl;
	}
	//析构函数
	~Person() {
		if (height != NULL)
		{
			delete height;
			height = NULL;//为了防止野指针出现,就将他置空
		}
		cout << "析构函数!" << endl;
	}
private:
	int age;
	int* height;
};



//调用有参的构造函数
void test01() {
	Person p1(18);
	Person p2(p1);//走的是拷贝构造函数,但是因为程序员没有设置拷贝构造,所以编译器按默认的拷贝构造函数,走,所以数出来的p2.age也是18
	//
}

void test02() {
	//现在建立两个参数的有参构造
	Person p3(18, 15);

	//调用结束,Person局部变量被释放,因此此时的15的在此时释放比较好,所以要回到类的析构函数中去释放
	//**********以下为关键部分内容,当有成员属性在堆区开辟的时候,涉及调用拷贝构造函数,在释放的时候就要出问题******************
	Person p4(p3);
//问题在哪?
//问题在于根据进栈顺序,先进后出,p4的变量先释放,即p4的析构函数被调用,函数体中有一段释放堆区内存的程序,因此p4按照逻辑就把15的内存空间给释放了
//而当p3去运行那段程序时,height的内存早已被释放了,因为程序崩溃!【重复释放内存】
//解决措施:在p4在进行p3拷贝的时候呢,调用自己构造的拷贝函数的时候直接让你那个height换一个地址,这样在释放的时候就各走各的了,实现深拷贝,但你要不在堆区释放空间,就没那么多事吧
}

int main() {

	
	//test01();
	test02();
	system("pause");

	return 0;
}

//如果在类对象属性的定义时,在堆区开辟了空间,那么一定要自己提供拷贝构造函数,实现深拷贝,即第30行的代码,防止浅拷贝带来的问题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值