【C++入门】4类与对象中-析构函数

目录

析构函数

概念

特性

析构函数的调用顺序


析构函数

概念

通过前面构造函数的学习,我们知道一个对象是怎么来的,那一个对象又是怎么没呢的?
析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由
编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。类似于之前常写的destroy函数。

特性

析构函数是特殊的成员函数,其特征如下:

1. 析构函数名是在类名前加上字符 ~。

2. 无参数无返回值类型。

3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载(本质原因就是清理结果是确定的,不像初始化的结果是多样的。构造函数只要想写,可以写一堆出来,但是析构函数是对资源的清理,说白就是各种置“零”

4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

typedef int DataType;
class Stack
{
public:
	Stack(size_t capacity = 3)
	{
		_array = (DataType*)malloc(sizeof(DataType) * capacity);
		if (NULL == _array)
		{
			perror("malloc申请空间失败!!!");
			return;
		}
		_capacity = capacity;
		_size = 0;
	}
	void CheckCapacity()
	{
		if (_capacity == _size)
		{
			int newcapacity = _capacity == 0 ? 4 : _capacity * 2;
			_capacity = newcapacity;
		
		DataType* tmp = (DataType*)malloc(sizeof(DataType)*newcapacity);
		if (tmp == NULL)
		{
			perror("malloc fail");
			exit(-1);
		}
		_array = tmp;
		}
	}

	void Push(DataType data)
	{
		CheckCapacity();
		_array[_size] = data;
		_size++;
	}
	// 其他方法...
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = NULL;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	DataType* _array;
	int _capacity;
	int _size;
};
void TestStack()
{
	Stack s;
	s.Push(1);
	s.Push(2);
}

int main()
{
	TestStack();

	return 0;

}

 

通过调试,我们发现析构函数确实做到了在对象的生命周期结束的时候,由编译器自动调用,完成了对对象资源的清理。

5. 关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器
生成的默认析构函数,对自定类型成员调用它的析构函数

class Time
{
public:
~Time()
{
cout << "~Time()" << endl;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
private:
// 基本类型(内置类型)
int _year = 1970;
int _month = 1;
int _day = 1;
// 自定义类型
Time _t;
};
int main()
{
Date d;
return 0;
}

 程序运行结束后输出:~Time()
在main方法中根本没有直接创建Time类的对象,为什么最后会调用Time类的析构函数?因为:main方法中创建了Date对象d,而d中包含4个成员变量,其中_year, _month,
_day三个是内置类型成员,销毁时不需要资源清理,最后系统直接将其内存回收即可;而_t是Time类对象,d销毁时,要将其内部包含的Time类的_t对象销毁,所以要调用Time类的析构函数。但是:main函数中不能直接调用Time类的析构函数,实际要释放的是Date类对象,所以编译器会调用Date类的析构函数,而Date没有显式提供,则编译器会给Date类生成一个默认的析构函数,目的是在其内部。所以这里的time函数是被编译器产生的Date对象的析构函数所间接调用的,而非直接调用。
调用Time类的析构函数,即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁
main函数中并没有直接调用Time类析构函数,而是显式调用编译器为Date类生成的默认析
构函数
注意:创建哪个类的对象则调用该类的析构函数,销毁那个类的对象则调用该类的析构函数

6. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如
Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。 申请资源具体指的就是有没有一些自定义类型向内存申请空间了,如果不去写自定义的析构函数的话,可能会造成内存泄漏。这里的Date类就很经典,因为其内部全是内置型的对象,系统不会对其进行资源清理,系统最后直接将其内存收回即可。

析构函数的调用顺序

下面来看一道例题:

设已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为?( )

C c;

int main()

{

A a;

B b;

static D d;

  return 0;

}

A.D B A C

B.B A D C

C.C D B A

D.A B D C

析构函数的调用顺序要从两个方面考察:首先是在程序运行时对象的声明周期,其次就是函数栈帧开辟与销毁时栈后进先出的特性。

基于这两点可得:

 局部对象的生命周期最短,因此也是最先去调用析构函数的,局部对象是在栈上分配的,后创建的对象先被销毁,这样可以确保资源的正确释放。其次就是局部的静态变量,局部静态对象的生命周期贯穿整个程序的执行过程,直到程序结束。再其次是全局对象,全局对象是在静态存储区分配的,后定义的对象先被销毁。

因此题目调用顺序是B A D C ,选B选项。

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C++面向对象编程函数函数是两个非常重要的概念。 函数是一种特殊的函数,它在对象被创建时自动调用,用于初始化对象的数据成员。函数的名称与类名相同,没有返回值类型,可以有参数,可以有多个函数,以便在创建对象时进行不同的初始化操作。 函数是一种特殊的函数,它在对象被销毁时自动调用,用于清理对象的资源。函数的名称与类名相同,前面加上一个波浪号(~),没有返回值类型,不接受任何参数。 函数函数是C++面向对象编程的两个重要概念,它们的作用是初始化对象和清理对象的资源,是面向对象编程的基础。 ### 回答2: 面向对象是一种程序设计的方法,它以对象心,通过封装、继承和多态等机制来组织和管理代码,使程序更加可靠、可重用和易于维护。其函数函数是面向对象程序设计的重要概念。 函数是一种特殊的成员函数,它在对象创建时自动被调用,用于对对象进行初始化。函数的名称与类名相同,没有返回值,可以重载,可以带参数,也可以不带参数。函数的作用是保证对象在创建时始终处于一种可靠的状态,从而避免程序运行时的错误和异常。 函数是与函数相对应的一种成员函数,它在对象销毁时自动被调用,用于对对象进行善后处理。函数的名称与类名相同,前面加上一个波浪号(~),没有参数,也没有返回值。函数的作用是释放对象所占用的资源,例如动态分配的内存、打开的文件、建立的连接等,在对象销毁之前要确保这些资源已经被回收,从而避免内存泄漏和资源浪费。 函数函数是面向对象程序设计的重要组成部分,它们体现了对象的生命周期和和管理方式,尤其是在涉及到动态内存分配和释放时更为重要。正确使用函数函数可以提高程序的可靠性、可重用性和可维护性,从而更好地实现程序模块化和复用。因此,在面向对象程序设计函数函数应该被视为重要的设计关注点,特别是在涉及到大型程序或长期运行的系统时。 ### 回答3: 面向对象编程是一种广泛使用的编程范式,它关注的是对象的行为和属性,而不是函数和逻辑。函数函数是面向对象编程的两个重要概念,在类的实例化和释放过程起到了关键的作用。 函数是一个类的特殊函数,它习惯性地与类名相同,用于初始化类的实例。函数可以接收参数,这些参数可以用来初始化类的成员变量。每当一个新的对象被创建时,函数会自动调用,以确保对象被正确地初始化。如果类没有定义函数,编译器将提供一个默认函数函数是一个类的另一个重要函数,它也习惯性地与类名相同,用于释放由该类创建的资源。函数通常用于释放内存、关闭打开的文件、关闭网络连接等等,以防止资源泄漏和造成程序崩溃。当一个对象被删除或销毁时,函数会自动调用,以确保类能够正确地清理资源。 需要注意的是,当一个对象被复制时,也会调用函数函数。使用深拷贝和浅拷贝来管理类的复制,以确保不会复制对象的私有数据。此外,有一些 C++ 特殊语法,如移动语义和智能指针等等,可以用于提高函数函数的效率和安全性。 总之,函数函数是面向对象编程不可或缺的两个概念。它们可以保证类的正确初始化和释放,从而防止资源泄漏和程序崩溃。编写好函数函数是编写高质量 C++ 代码的关键。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值