1. 概念
前面通过构造函数的学习,我们知道一个对象时怎么来的,那一个对象又是怎么没呢的?
析构函数:与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。
同构造函数不是去申请空间一样,析构函数也不是去释放空间,而是完成资源清理工作,即在栈上定义的对象都是编译器来帮助释放而不是析构函数来释放。
什么是清理?首先需要搞清楚那些成员是属于对象的,那些成员是不属于对象的,针对那些不属于对象的就是清理。
class A {
public:
A(int sz = 10) {
_pi = (int*)malloc(sizeof(int)*sz);
}
~A() {
if (_pi) {
free(_pi);
_pi = nullptr;
}
}
private:
int* _pi;
};
int main() {
A a(20);
system("pause");
return 0;
}
主函数中申请了20个int类型大小连续的空间,首先实例化时会调构造函数,调完之后,主函数执行完毕会自动调用析构函数,由于在创建对象的时候申请了一片20大小的连续空间,此时析构函数就会完成这片空间的清理工作,释放已申请的资源,但是这个时候A对象并没有被析构函数销毁,这并不是析构函数干的事情,而是编译器该干的事情。也就是目前对象的成员指针仍然存在,只有当程序执行完毕后,编译器去销毁这个对象,将这片的空间也释放。对于这个对象来讲,它里面存放的只有int类型指针,它只占4个字节的大小。而刚申请的20个整形的连续空间它是资源,不属于这个对象,是由析构函数帮助清理资源,而对象的销毁由编译器来操作。
2. 特性
析构函数是特殊的成员函数。
其特征如下:
1)析构函数名是在类名前加上字符 ~。
2)无参数无返回值。
3)一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
4)对象生命周期结束时,C++编译系统系统自动调用析构函数。
5)关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器生成的默认析构函数,对会自定类型成员调用它的析构函数。
class String {
public:
String(const char* str = "jack") {
_str = (char*)malloc(strlen(str) + 1);
strcpy(_str, str);
}
~String() {
cout << "~String()" << endl;
free(_str);
}
private:
char* _str;
};
class Person {
private:
String _name;
int _age;
};
int main() {
Person p;
system("pause");
return 0;
}