C++教程:C++析構函數詳解
2020-05-23 14:25:55
供稿:網友
在學習鏈表的時候,我們知道結點是動態生成的,如果在程序結束之前不釋放內存,就會造成內存泄漏。雖然我們已經編寫了成員函數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輸出我們發現,當一個對象的成員數據還是對象時,析構函數的運行順序恰好與構造函數的運行順序相反:一個大對象先調用析構函數,瓦解成若干成員數據,然后各個成員數據再調用各自的析構函數。這體現出構造函數與析構函數的對稱性。