【C++第二阶段】深浅拷贝与成员属性初始化-20240203

你好你好!
以下内容仅为当前认识,可能有不足之处,欢迎讨论!



深拷贝与浅拷贝

场景:如果在类中,出现了成员属性是指针,指针指向的是一块地址。那么,在类中,利用构造函数给该指针在内存空间—堆区开辟空间,需要在析构函数中由开发者销毁这块空间。这对于一个对象来说没有问题。但是,若两个及以上的对象,如果还是使用浅拷贝(系统拷贝构造函数),就会出现问题——对于第二个对象销毁的对象——指针指向的地址——是什么呢?

比如以下代码:

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

//#include"Person.h"
//#include"section2functions.h"

class Person {
public:

	int* person_age;
	Person() {
		cout << "==================" << endl;
		cout << "无参构造函数调用。" << endl;
		cout << "==================\n" << endl;
	}
	Person(int age) {
		person_age = new int(age);//在堆区中开辟的空间,需要在析构函数中手动释放。
		cout << "==================" << endl;
		cout << "有参构造函数调用。" << endl;
		cout << "==================\n" << endl;
	}

	~Person() {
		if (person_age) {
			delete person_age;
			person_age = NULL;
		}
		cout << "==============" << endl;
		cout << "析构函数调用。" << endl;
		cout << "==============\n" << endl;
	}
};

void test_22() {
	Person p_orginal = Person(20);
	cout << "p_orginal年龄为:" << *p_orginal.person_age << "." << endl;

	Person p_after(p_orginal);
	cout << "p_after的年龄为:" << *p_after.person_age << "." << endl;
}

int main() {
	cout << "hello world !" << endl;

	test_22();

	system("pause");
	return 0;
}

运行结果如图:

image-20240202154113256

可以看到运行到第二个析构函数的调用时发生了错误,为什么?因为析构函数是对象销毁前调用的,但第一个对象销毁时,把浅拷贝中的堆区的内存给释放了,导致在第二个对象删除指针时,不知道应该释放堆区哪块地址,从而报错。

何以解决?自定义拷贝构造函数并避免重复释放。

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

class Person {
public:

	int* person_age;
	Person() {
		cout << "==================" << endl;
		cout << "无参构造函数调用。" << endl;
		cout << "==================\n" << endl;
	}
	Person(int age) {
		person_age = new int(age);//在堆区中开辟的空间,需要在析构函数中手动释放。
		cout << "==================" << endl;
		cout << "有参构造函数调用。" << endl;
		cout << "==================\n" << endl;
	}

	//重写拷贝构造函数
	Person(const Person &person) {
		person_age = new int(*person.person_age);
		//手动开辟另一块内存空间,从而释放时不重复释放。
		cout << "==================" << endl;
		cout << "拷贝构造函数调用。" << endl;
		cout << "==================\n" << endl;
	}

	~Person() {
		if (person_age) {
			delete person_age;
			person_age = NULL;
		}
		cout << "==============" << endl;
		cout << "析构函数调用。" << endl;
		cout << "==============\n" << endl;
	}
};

void test_22() {
	Person p_orginal = Person(20);
	cout << "p_orginal年龄为:" << *p_orginal.person_age << "." << endl;

	Person p_after(p_orginal);
	cout << "p_after的年龄为:" << *p_after.person_age << "." << endl;
}

int main() {
	cout << "hello world !" << endl;

	test_22();

	system("pause");
	return 0;
}

运行结果,可以看到调用了两次析构函数,成功释放掉内存。
image-20240202154903393


类和对象——成员函数的初始化

用途:用在成员属性的初始化上。

代码:

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

class Person {
	int person_age;
public :
	Person() {
		cout << "==================" << endl;
		cout << "无参构造函数调用。" << endl;
		cout << "==================" << endl;
	}
	Person(int age) :person_age(age) {
		cout << "==================" << endl;
		cout << "有参构造函数调用。" << endl;
		cout << "==================" << endl;
	}
	~Person() {
		cout << "==================" << endl;
		cout << "=析构函数的调用。=" << endl;
		cout << "==================" << endl;
	}
	void print_age() {
		cout << "person age = " << person_age << "." << endl;
	}
};

void test2_2_20() {
	int age = 20;
	Person person(age);
	person.print_age();
}

int main() {
	cout << "hello world !" << endl;

	test2_2_20();

	system("pause");
	return 0;
}

运行结果:

image-20240202205723518

可以看到在构造函数后方写类名:成员属性(属性值),...,成员属性(属性值)可以帮助初始化成员属性。


以上是我的学习笔记,希望对你有所帮助!
如有不当之处欢迎指出!谢谢!

学吧,学无止境,太深了

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HelpFireCode

随缘惜缘不攀缘。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值