解構函式與建構函式
何時呼叫建構函式和解構函式
建構函式的作用是保證每個物件的資料成員都有何時的初始值。
解構函式的作用是回收記憶體和資源,通常用於釋放在建構函式或物件生命期內獲取的資源。
一般我們都知道構造和析構的次序:
構造從類層次的最根處開始,在每一層中,首先呼叫基類的建構函式,然後呼叫成員物件的建構函式。析構則嚴格按照與構造相反的次序執行,該次序是唯一的,否則編譯器將無法自動執行析構過程。
建構函式和解構函式都是由編譯器隱式呼叫的。這些函式的呼叫順序取決於程式的執行進入和離開例項化物件時所在的那個作用域的順序。一般而言,解構函式的呼叫順序和建構函式的呼叫順序相反,但是,物件的儲存類可以改變解構函式的呼叫順序。
對於在全域性作用域中定義的物件,它們的建構函式是在檔案中所有其他函式(包括main)開始執行之前被呼叫的(但無法保證不同檔案的全域性物件建構函式的執行順序)。對應的解構函式是在終止main之後呼叫的。
exit函式會迫使程式立即終止,而不會執行自動物件的解構函式。這個函式經常用來在檢測到輸入錯誤或者程式所處理的檔案無法開啟時終止程式。
abort函式與exit函式功能相似,但它會迫使程式立即終止,而不允許呼叫任何物件的解構函式。abort函式通常用來表明程式的非正常終止。
自動區域性變數的建構函式是在程式的執行到達定義這個物件的位置時呼叫的,而對應的解構函式是在程式離開這個物件的作用域時呼叫的(即定義這個物件的程式碼完成了執行)。每次執行進入和離開自動物件的作用域時,都會呼叫它的建構函式和解構函式。如果程式呼叫了exit
靜態區域性物件的解構函式只調用一次,即執行首次到達定義這個物件的位置時。對應的解構函式是在main終止或程式呼叫exit函式時呼叫的。
全域性物件和靜態物件是以建立它們時相反的順序銷燬的。如果程式由於呼叫了exit函式而終止,則不會呼叫靜態物件的解構函式。
下面的demo演示了在幾個作用域不同的儲存類的CreateAndDestory的類的物件,它們的建構函式和解構函式的呼叫順序。
- #include <iostream>
- #include <string>
- using namespace std;
- class
Demo - {
- public:
- Demo(int,string); //建構函式
- ~Demo(); //解構函式
- private:
- int objectID; //ID number for object
- string message; //message describing object
- };
- Demo::Demo(int ID,string messagestring)
- {
- objectID = ID; //set object’s ID number
- message = messagestring; //set object’s descriptive message
- cout<<“Object “<<objectID<<” constructor runs “<<message<<endl;
- }
- Demo::~Demo()
- {
- cout<<(objectID==1 || objectID==6 ? “\n” : “”);
- cout<<“Object “<<objectID <<” destructor runs “<<message<<endl;
- }
- void create(void);
- Demo first(1,“(main 前的全域性物件)”); //在全域性作用域下定義first物件。它的建構函式是在執行main中的任何語句之前呼叫的
- //而它的解構函式是在已經運行了所有其他物件的解構函式之後,程式終止時呼叫
- int _tmain(int argc, _TCHAR* argv[])
- {
- cout<<“\n main 函式開始執行:”<<endl;
- Demo second(2,“(main 函式中的區域性自動物件)”);
- static Demo third(3,“(main 函式中的靜態區域性物件)”);
- create();
- cout<<“\n main 函式:繼續執行”<<endl;
- Demo fourth(4,“(main 函式中的區域性自動物件)”);
- cout<<“\n main 函式:執行結束”<<endl;
- system(“pause”);
- return 0;
- }
- void create(void)
- {
- cout<<“\n create 函式:開始執行”<<endl;
- Demo fifth(5,“(cerate 函式裡的本地自動物件)”);
- static Demo sixth(6,“(cerate 函式裡的本地靜態物件)”);
- Demo seventh(7,“(cerate 函式裡的本地自動物件)”);
- cout<<“\ncerate 函式:執行結束”<<endl;
- }
執行結果:
Object 6 destructor runs (cerate 函式裡的本地靜態物件)
Object 3 destructor runs (main函式中的本地靜態物件)
Object 1 destructor runs (main函式前的全域性物件)
分析:
Main函式中聲明瞭3個物件,second物件,fourth物件,是區域性自動物件,而third物件是一個靜態區域性物件。當執行到達物件的宣告位置時,才會呼叫這些物件的建構函式。
當執行到達mian的末尾時,首先呼叫fourth物件的解構函式,然後是second物件的解構函式。由於third物件是靜態的,因此它會存活到程式終止。呼叫third物件的解構函式的時機,是在呼叫全域性物件first的解構函式之前,但在所有其他物件被銷燬之後。
Create函式聲明瞭3個物件,其中fifth和seventh是區域性自動物件,sixth是靜態區域性物件。當create終止時,首先呼叫seventh物件的解構函式,然後是fifth物件的解構函式。由於sixth物件是靜態的,因此它會存活到程式終止。呼叫sixth物件的解構函式的時機,是在呼叫third和first的解構函式之前,但在所有其他物件被銷燬之後。
參考資料:《c++程式設計師教程》 電子工業出版社 張良華 譯 P259-262