您当前的位置:首页 > 计算机 > 编程开发 > VC/VC++

C++析构函数详解

时间:01-10来源:作者:点击数:

在学习链表的时候,我们知道结点是动态生成的,如果在程序结束之前不释放内存,就会造成内存泄漏。虽然我们已经编写了成员函数Destroy来删除所有动态生成的结点,但是如果我们不知道这个链表对象何时不再使用,那么调用Destroy的时机对我们来说就是个麻烦了。如果过早地调用,则后面的程序可能会出错。既然有构造函数能随着对象的创建而自动被调用,那么有没有一种函数能随着对象的消亡而自动被调用呢?有!那就是析构函数(Destructor)

析构函数是一种随着对象消亡而自动被调用的函数,它的主要用途是释放动态申请的资源。它没有返回类型,没有参数,也没有重载。析构函数的函数名也是指定的,是在构造函数名之前加一个“~”符号。

下面我们为程序15.4.2添上析构函数的功能:(程序15.5)

//node.h

#include <iostream>
using namespace std;
class Node//定义一个链表结点类
{
   public:
   Node();//构造函数的声明
   Node(Node &n);//结点拷贝构造函数
   Node(int i,char c='0');//构造函数重载1
   Node(int i,char c,Node *p,Node *n);//构造函数重载2
   ~Node();//结点析构函数
   int readi() const;//读取idata
   char readc() const;//读取cdata
   Node * readp() const;//读取上一个结点的位置
   Node * readn() const;//读取下一个结点的位置
   bool set(int i);//重载,通过该函数修改idata
   bool set(char c);//重载,通过该函数修改cdata
   bool setp(Node *p);//通过该函数设置前驱结点
   bool setn(Node *n);//通过该函数设置后继结点
   private:
   int idata;//存储数据保密
   char cdata;//存储数据保密
   Node *prior;//前驱结点的存储位置保密
   Node *next;//后继结点的存储位置保密
};
//未定义的函数与程序15.4.1相同
Node::~Node()
{
   cout <<"Node destructor is running..." <<endl;
}

//linklist.h

#include "node.h"//需要使用链表结点类
#include <iostream>
using namespace std;
class Linklist
{
   public:
   Linklist(int i,char c);//链表类构造函数
   Linklist(Linklist &l);//链表深拷贝构造函数
   ~Linklist();//链表析构函数
   bool Locate(int i);//根据整数查找结点
   bool Locate(char c);//根据字符查找结点
   bool Insert(int i=0,char c='0');//在当前结点之后插入结点
   bool Delete();//删除当前结点
   void Show();//显示链表所有数据
   void Destroy();//清除整个链表
   private:
   Node head;//头结点
   Node * pcurrent;//当前结点指针
};
//未定义的函数与程序15.4.2相同
Linklist::~Linklist()
{
   cout<<"Linklist destructor is running..."<<endl;
   Destroy();//一个成员函数调用另一个成员函数不需要带上对象名
}

//main.cpp 同程序15.4.2

运行结果:
          请输入一个整数和一个字符:
          4 G
          Node constructor is running...
          Linklist constructor is running...
          Node constructor is running...
          Node constructor is running...
          Node constructor is running...
          After Insert
          4 G
          3 F
          2 B 
          1 C
          Node destructor is running...
          After Delete
          4 G
          3 F
          1 C
          Linklist Deep cloner running...
          Node constructor is running...
          Node constructor is running...
          This is Linklist b
          4 G
          3 F
          1 C
          Node destructor is running...
          Node destructor is running...
          After Destroy
          4 G
          This is Linklist b
          4 G
          3 F
          1 C
          Linklist destructor is running...
          Node destructor is running...
          Node destructor is running...
          Node destructor is running...
          Linklist destructor is running...
          Node destructor is running...

在After Destroy之前的两条Node destructor运行是因为调用了a.Destroy(),最后的6条destructor是因为程序运行结束使得对象自动消亡。可见析构函数是在使用delete语句删除动态生成的对象或程序结束对象消亡时自动被调用的。

从最后的2条destructor输出我们发现,当一个对象的成员数据还是对象时,析构函数的运行顺序恰好与构造函数的运行顺序相反:一个大对象先调用析构函数,瓦解成若干成员数据,然后各个成员数据再调用各自的析构函数。这体现出构造函数与析构函数的对称性。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
上一篇:链表类 下一篇:C++拷贝构造函数
推荐内容
相关内容
栏目更新
栏目热门