C++57个入门知识点_21_ 析构函数的调用(主程序结束前自动跳入对象析构函数,析构函数中使用free()函数就可实现对象资源的释放;内存泄漏:内存没有得到释放;不指定大小的数组定义方法:指针)

上两篇C++57个入门知识点_19_ 构造函数的作用及写法(作用:用于对象初始化,定义时候就定义对象初值;写法:函数名是类名;不写函数返回值;参数可以有也可以没有;使用:CStudent stu(“张三“)C++57个入门知识点_20_ 构造函数的调用(不同参数构造函数调用方法;默认无参构造函数;C++语法中的关键字:explicit显示调用、=default使用默认构造、=delete禁止使用某函数)我们介绍C++类的构造函数的相关内容,本篇开始将会介绍与构造函数紧密联系的函数-析构函数

总结: C++中语法定义,主程序在结束前会自动跳入对象的析构函数,在析构函数中使用free()函数就可实现对象资源的释放。
1. 析构函数定义:完成的资源的反初始化,资源的释放;
2. 析构函数写法: ~CStudent() {}

  • 类名前加~
  • 通常是由编译器决定调用时机,不需要手动调用
  • 析构函数没有参数和返回值

3. 析构函数不能重载(结合函数重载需要满足函数名相同,参数列表不同分析)
4. 申请的内存,必须要使用free()函数释放掉,否则就会造成 内存泄漏(内存没有得到有效释放)
5. 类中的成员变量char m_szName[255];,代表了255个字节大小的char类型数组,为了想让其不是固定的大小,可以使用char* m_szName;指针代表指向的地址,不会限制住m_szName的大小

1. 析构函数定义

构造函数用于完成对象的初始化(对象成员的赋值),析构是构造相反的过程,其作用为:完成的资源的反初始化,资源的释放

C++的语法就是在模仿人的动作行为,举例子:人有生就会有死,对象有创建的过程,也就会有消亡的过程。

利用以下代码分析:在CStudent stu1;时就会跳入构造函数CStudent () {},完成成员的初始化。

#include <iostream>

class CStudent {

public:
	CStudent() {
		printf("CStudent()\r\n");
     }
	void SetName(const char* pszName)
	{
		strcpy_s(m_szName, pszName);//m_szName并未定义大小,存在溢出风险,系统提示使用strcpy_s
	}
	
private:
	int m_nStudID;//学号
	char m_szName[255];//255个字节的缓冲区,姓名
};

int main(int argc, char* argv[])
{
	CStudent stu1;
	return 0;
}

我们对程序进行修改,类中的成员变量char m_szName[255];,代表了255个字节大小的char类型数组,为了想让其不是固定的大小,可以使用char* m_szName;指针代表指向的地址,不会限制住m_szName的大小

使用malloc()函数申请动态堆内存,其使用可参考C语言基础入门48篇_46_malloc与free(malloc申请堆返回void要指针强转、free释放堆,只需堆内存首地址、malloc配合sizeof增加可读性、注意出{}作用域导致无法释放)

#include <iostream>

class CStudent {

public:
	CStudent() {
		//为了m_szNam创建一个堆空间(分配动态内存)
		//c语言中在堆上创建动态内存,(char*)malloc(255)中255代表大小,malloc(255)返回一个void*,使用(char*)进行强转
		m_szName = (char*)malloc(255);
     }

	void SetName(const char* pszName)
	{	}

private:
	int m_nStudID;
	char* m_szName;
};

int main(int argc, char* argv[])
{
	CStudent stu1;

	return 0;
}

在构造函数中使用m_szName = (char*)malloc(255);char* m_szName; 动态分配了255个字节的堆空间内存
在这里插入图片描述
继续运行,return 0main函数结束的地方,堆内存依然存在,什么时候会不存在呢?
在这里插入图片描述
根据之前C语言中的知识可知,需要利用free()函数进行释放

#include <iostream>

class CStudent {

public:
	CStudent() {
		//为了m_szNam创建一个堆空间(分配动态内存)
		//c语言中在堆上创建动态内存,(char*)malloc(255)中255代表大小,malloc(255)返回一个void*,使用(char*)进行强转
		m_szName = (char*)malloc(255);
		free(m_szName);
     }

	void SetName(const char* pszName)
	{	}

private:
	int m_nStudID;//学号
	char* m_szName;
};

int main(int argc, char* argv[])
{
	CStudent stu1;

	return 0;
}

运行后:内存得到释放,内存中的dd代表了内存释放了
在这里插入图片描述

2. 析构函数写法及性质

2.1 析构函数写法: ~CStudent() {}

  • 类名前加~
  • 通常是由编译器决定调用时机,不需要手动调用
  • 析构函数没有参数和返回值

2.2 析构函数不能重载(结合函数重载需要满足函数名相同,参数列表不同分析)

申请的内存,必须要使用free()函数释放掉,否则就会造成内存泄漏(内存没有得到有效释放),问题就来了,什么时候调用free()函数最为合适?
不再使用stu1对象的时候去释放,但是如果让程序员去判断释放的时机就会显得十分麻烦,所以C++提供了一种语法,称为 析构函数:在类的对象即将死亡时,就会调用析构函数

#include <iostream>

class CStudent {

public:
	CStudent() {
		//为了m_szNam创建一个堆空间(分配动态内存)
		//c语言中在堆上创建动态内存,(char*)malloc(255)中255代表大小,malloc(255)返回一个void*,使用(char*)进行强转
		m_szName = (char*)malloc(255);

		//free(m_szName);
     }
	~CStudent() {
		printf("~CStudent()\r\n");
	}

	void SetName(const char* pszName){}

private:
	int m_nStudID;//学号
	char* m_szName;
};

int main(int argc, char* argv[])
{
	CStudent stu1;

	return 0;
}

F10单步调试:return 0之后就会退出main()函数,因此在这步之前需要进行析构

  • return 0之前申请好动态内存
    在这里插入图片描述
  • 随后跳入析构函数
    在这里插入图片描述
  • free(m_szName);放入析构函数中是最合适的,也就可以实现内存的释放
    在这里插入图片描述

3.学习视频地址:C++57个入门知识点_21_ 析构函数的调用

4.学习笔记:


#include <iostream>

//构造与析构

//析构函数
//1.作用:完成的资源的反初始化,资源的释放
//2.析构函数写法:	~CStudent() {}
//	(1)类名前加~
//	(2)通常是由编译器决定调用实际,不需要手动调用
//	(3)析构函数没有参数和返回值
//3.析构函数不能重载

class CStudent {

public:
	//无参构造函数
	CStudent() {
			
		//为了m_szNam创建一个堆空间(分配动态内存)
		//m_szName = (char*)malloc(255);//c语言中在堆上创建动态内存
		//free(m_szName);//c语言描述释放内存,内存没有得到有效的释放,就是内存泄漏

	}
	
	//析构函数
	~CStudent() {

		free(m_szName);//将参数的资源释放

	}

	void SetName(char* pszName)
	{
		//存在缓冲区溢出的风险,pszName并不知道指向的字符串的大小,若大于255,则可能将原来字符串末尾覆盖
		//strcpy_s(m_szName,pszName);//m_szName并未定义大小,存在溢出风险,系统提示使用strcpy_s

		}

private:
	int m_nStudID;//学号

	//指针代表指向的地址,不会限制住m_szName的大小,相对于预定义好的缓冲,避免了溢出的风险
	char* m_szName;
};

int main(int argc,char* argv[])
{
	CStudent stu;

	return 0;
}


5.特别注意:
(1) 使用指针的好处:

	//指针代表指向的地址,不会限制住m_szName的大小,相对于预定义好的缓冲,避免了溢出的风险
	char* m_szName;

(2) C语言中堆上创建动态内存及释放:

		//m_szName = (char*)malloc(255);//c语言中在堆上创建动态内存
		//free(m_szName);//c语言描述释放内存,内存没有得到有效的释放,就是内存泄漏

(3) 析构函数的调用顺序:
在主函数return 0;之前进行析构

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十月旧城

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值