析构函数
析构函数的介绍
与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统会自动执行析构函数。以C++语言为例:析构函数名也应与类名相同,只是在函数名前面加一个位取反符,例如stud( ),以区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数(即使自定义了析构函数,编译器也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器在执行时会先调用自定义的析构函数再调用合成的析构函数),它也不进行任何操作。所以许多简单的类中没有用显式的析构函数。–百度百科
析构函数的使用
- 析构函数名是在类名前加上字符 ~。
- 无参数无返回值类型。
- 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
- 析构函数不能重载
- 对象生命周期结束时,C++编译器自动调用析构函数。
class Person
{
public:
~Person()//析构函数
//注意:真正实用的析构函数一般是不含有输出信息的。
{
cout << "~person()" << endl;
}
private:
int _phoneNumber;
int _adress;
int _name;
};
class Date
{
private:
// 基本类型(内置类型)
int _year = 1970;
int _month = 1;
int _day = 1;
// 自定义类型
Person _t;
};
int main()
{
Date d;
return 0;
}
编译器调用析构函数对于内置类型与自定义类型的不同之处
如下代码
程序运行结束后输出:~Person() 在main方法中根本没有直接创建Person类的对象,为什么最后会调用Person类的析构函数?
main方法中创建了Date对象d,而d中包含4个成员变量,其中_year, _month, _day三个是内置类型成员,销毁时不需要资源清理,最后系统直接将其内存回收即可;而_t是person类对象,所以在d销毁时,要将其内部包含的person类的_t对象销毁,所以要调用person类的析构函数。但是:main函数中不能直接调用person类的析构函数,实际要释放的是Date类对象,所以编译器会调用Date类的析构函数(~Date),而Date没有显式提供,则编译器会给Date类生成一个默认的析构函数,目的是在其内部调用person类的析构函数,
即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁,main函数中并没有直接调用person类析构函数,而是显式调用编译器为Date类生成的默认析构函数
注意:
销毁哪个类的对象则调用哪个类的析构函数,若该类中有自定义类型则,调用本类的析构函数在其内部调用自定义类型对象的析构函数
#include<iostream>
using namespace std;
class Person
{
public:
~Person()
{
cout << "~person()" << endl;
}
private:
int _phoneNumber;
int _adress;
int _name;
};
class Date
{
private:
// 基本类型(内置类型)
int _year = 1970;
int _month = 1;
int _day = 1;
// 自定义类型
Person _t;
};
int main()
{
Date d;
return 0;
}
显示定义析构函数
如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏。