在之前的博客中,我们介绍了构造函数和拷贝构造函数。他们的作用都是将对象进行初始化。今天,我要介绍在类中的另一种函数,叫做析构函数。
析构函数的函数名为~+类名。和构造函数一样,析构函数也是没有返回值的,也不用写void。但是由于它没有任何参数,所以它肯定是不能被重载的。若用户没有定义析构函数,那么系统会自动生成一个析构函数,这个析构函数并不起任何作用。
析构函数在对象被销毁之前被自动调用,它的作用是将对象中的成员占用的内存归还给操作系统。为了观察析构函数被调用的时机,我们在析构函数下加上打印析构函数名的代码,看它在控制台中被打印出来的位置。
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
Student()
{
cout << "Student()" << endl;
}
~Student()
{
cout << "~Student()" << endl;
}
private:
string m_strName;
};
int main(void)
{
Student stu;
system("PAUSE");
return EXIT_SUCCESS;
}
我们写了这样的一串代码,在类中定义了构造函数和析构函数,由于我们没有在函数定义里写任何有实际意义的代码,所以这两个函数不起任何实际作用,只是“刷一下存在感”,在调用的时候打印一行字。在main函数中,我们只是实例化了一个对象,不对对象进行任何操作。
这个时候,我们看到,只调用了构造函数,析构函数还是没有被调用。这时候,我们按下任意键。
可以看到,在程序结束运行之后,析构函数被调用了出来。这就说明了,如果从栈中实例化一个对象,那么对象会在程序结束后被自动销毁,内存会被自动归还,析构函数也在这个时候被调用。
那么,如果是从堆中实例化对象,那么析构函数会在哪里被调用呢?我们将main函数改成这样。
int main(void)
{
Student* p = new Student();
delete p;
p = NULL;
system("PAUSE");
return EXIT_SUCCESS;
}
我们从堆中实例化了一个对象指针p,不进行任何操作,直接释放内存,然后使指针悬空。我们看一下运行结果。
我们发现,程序还没有结束运行,析构函数就已经被调用。这也就说明了,从堆中实例化对象,在执行delete的时候被手动销毁,这个时候系统就会调用析构函数。
这一次,我们主要讲解析构函数在什么时候会被调用,如果想知道析构函数如何发挥它真正的作用,我们会在用到对象成员指针的时候进行介绍。
以上就是此篇博客的内容,下一篇:对象数组。