您现在的位置是:首页 > 编程 > 

【C++】深入剖析默认成员函数2:析构函数

2025-07-19 16:48:05
【C++】深入剖析默认成员函数2:析构函数 继上一个有点令我头大的构造函数后,真是一波未平一波又起呀,咱们又迎来新的默认成员函数:析构函数!别说,我真的一脸懵了~上一篇构造函数,我们简单地了解到了第一个默认成员函数---构造函数的各种便利,总而言之,构造函数就是初始化一个对象,那清理一个对象----便是析构函数咯。在数据结构中我们有实现过Init(初始化,也可以看做相似于构造函数),destroy

【C++】深入剖析默认成员函数2:析构函数

继上一个有点令我头大的构造函数后,真是一波未平一波又起呀,咱们又迎来新的默认成员函数:析构函数!

别说,我真的一脸懵了~

上一篇构造函数,我们简单地了解到了第一个默认成员函数---构造函数的各种便利,总而言之,构造函数就是初始化一个对象,那清理一个对象----便是析构函数咯。

在数据结构中我们有实现过Init(初始化,也可以看做相似于构造函数),destroy(销毁,就可以看做相似于析构函数)

析构函数的概念:

析构函数与构造函数功能相反,构造函数主要是初始化,但不开空间

析构函数主要清理但不销毁对象

这样理解还是很容易的

析构函数的特点:

同样的,析构函数也是特殊的默认成员函数,有以下特点:

  • 1.析构函数名是在类名前加上字符 ~。
  • 2. ⽆参数⽆返回值。 (这⾥跟构造类似,也不需要加void)
  • .⼀个类只能有⼀个析构函数。若未显式定义,系统会⾃动⽣成默认的析构函数。
  • 4. 对象⽣命周期结束时,系统会⾃动调⽤析构函数。
Date类:

代码示例:

代码语言:javascript代码运行次数:0运行复制
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 0) {
		_year = year;
		_month = month;
		_day = day;
	}
	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	~Date() {
		cout << "~Date()" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};


int main()
{
	Date d1;
	d1.Print();
	return 0;
}

运行结果:

我们从这里可以看出,析构函数自动调用啦!

析构函数还有一个特性:先进行构造的对象后析构:

代码示例如下:

代码语言:javascript代码运行次数:0运行复制
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 0) {
		_year = year;
		_month = month;
		_day = day;
	}
	void Print() {
		cout << _year << "-" << _month << "-" << _day << endl;
	}
	~Date() {
		cout << "~Date()" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};


int main()
{
	Date d1;
	Date d2(2024, 12, 21);
	return 0;
}

运行结果:

第一个箭头析构的是对象d2,第二个就是对象d1哒

刚刚上面使用了常见的日期类来做举例,接下来就要用我们熟悉的老朋友Stack类来举个例子啦

Stack类:

代码如下:

代码语言:javascript代码运行次数:0运行复制
typedef int STDataType;
class Stack
{
public:
	Stack(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;
		_top = 0;
	}
	~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};

int main()
{
	Stack st1;
	Stack st2(10);
	return 0;
}

运行结果:

在此相应的上面一个箭头是st2的析构,下面一个箭头是st1的析构

重点:

就是Stack类的析构不能单纯地靠编译器给的默认析构函数来进行析构,这样会造成资源的泄露,因为Stack类中有进行资源的申请,一定要自己写析构!!!

当然还有一个MyQueue类也是不需要我们去实现析构的

MyQueue类:

代码实现如下:

代码语言:javascript代码运行次数:0运行复制
typedef int STDataType;
class Stack
{
public:
	Stack(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;
		_top = 0;
	}
	~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};
// 两个Stack实现队列
class MyQueue
{
public:
	//编译器默认⽣成MyQueue的析构函数调⽤了Stack的析构,释放的Stack内部的资源
		// 显⽰写析构,也会⾃动调⽤Stack的析构
	~MyQueue() {
		cout << "MyQueue()" << endl;
	}
private:
	Stack pushst;
	Stack popst;
};
int main()
{
	Stack st1;
	Stack st2(10);

	MyQueue mq;
	return 0;
}

运行结果:

这就是MyQueue类的析构,这就很有趣啦,因为MyQueue类是使用了Stack类中的资源,而没有自己创建资源,所以可以使用编译器生成的默认析构函数。

析构函数的补充要点:

跟构造函数类似,我们不写编译器⾃动⽣成的析构函数对内置类型成员不做处理,⾃定类型成员会调⽤他的析构函数。 (对于内置类型的成员变量,不做处理;对于自定义类型的成员变量,会自动调用默认的析构函数)

还需要注意的是我们显⽰写析构函数,对于⾃定义类型成员也会调⽤他的析构,也就是说⾃定义类

型成员⽆论什么情况都会⾃动调⽤析构函数。

总而言之,就是编译器总会在你需要的时候出手帮你,但你也不能完全靠编译器。

以上就是对于析构函数的理解

有问题希望佬们及时指出哦~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2024-12-21,如有侵权请联系 cloudcommunity@tencent 删除stack编译器对象函数c++

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1143588.html

相关标签:无
上传时间: 2025-07-19 09:28:14
留言与评论(共有 6 条评论)
本站网友 奥运海报
14分钟前 发表
也会⾃动调⽤Stack的析构 ~MyQueue() { cout << "MyQueue()" << endl; } private
本站网友 宁海房屋出租
26分钟前 发表
系统会⾃动⽣成默认的析构函数
本站网友 蔓延视觉婚纱摄影
4分钟前 发表
也会⾃动调⽤Stack的析构 ~MyQueue() { cout << "MyQueue()" << endl; } private
本站网友 老人之恋
12分钟前 发表
如有侵权请联系 cloudcommunity@tencent 删除前往查看stack编译器对象函数c++
本站网友 assembly文件夹
6分钟前 发表
一定要自己写析构!!!当然还有一个MyQueue类也是不需要我们去实现析构的MyQueue类:代码实现如下:代码语言:javascript代码运行次数:0运行复制typedef int STDataType; class Stack { public