建立對象時系統會自動調用構造函數進行初始化工做,一樣,銷燬對象時系統也會自動調用一個函數來進行清理工做,例如釋放分配的內存、關閉打開的文件等,這個函數就是析構函數。
析構函數(Destructor)也是一種特殊的成員函數,沒有返回值,不須要程序員顯式調用(程序員也無法顯式調用),而是在銷燬對象時自動執行。構造函數的名字和類名相同,而析構函數的名字是在類名前面加一個~
符號。
注意:析構函數沒有參數,不能被重載,所以一個類只能有一個析構函數。若是用戶沒有定義,編譯器會自動生成一個默認的析構函數。
上節咱們定義了一個 VLA 類來模擬變長數組,它使用一個構造函數爲數組分配內存,這些內存在數組被銷燬後不會自動釋放,因此很是有必要再添加一個析構函數,專門用來釋放已經分配的內存。請看下面的完整示例:html
#include <iostream> using namespace std; class VLA{ public: VLA(int len); //構造函數 ~VLA(); //析構函數 public: void input(); //從控制檯輸入數組元素 void show(); //顯示數組元素 private: int *at(int i); //獲取第i個元素的指針 private: const int m_len; //數組長度 int *m_arr; //數組指針 int *m_p; //指向數組第i個元素的指針 }; VLA::VLA(int len): m_len(len){ if(len > 0){ m_arr = new int[len]; /*分配內存*/ } else{ m_arr = NULL; } } VLA::~VLA(){ delete[] m_arr; //釋放內存 } void VLA::input(){ for(int i=0; m_p=at(i); i++){ cin>>*at(i); } } void VLA::show(){ for(int i=0; m_p=at(i); i++){ if(i == m_len - 1){ cout<<*at(i)<<endl; } else{ cout<<*at(i)<<", "; } } } int * VLA::at(int i){ if(!m_arr || i<0 || i>=m_len){ return NULL; } else{ return m_arr + i; } } int main(){ //建立一個有n個元素的數組(對象) int n; cout<<"Input array length: "; cin>>n; VLA *parr = new VLA(n); //輸入數組元素 cout<<"Input "<<n<<" numbers: "; parr -> input(); //輸出數組元素 cout<<"Elements: "; parr -> show(); //刪除數組(對象) delete parr; return 0; }
運行結果:
Input array length: 5
Input 5 numbers: 99 23 45 10 100
Elements: 99, 23, 45, 10, 100
~VLA()
就是 VLA 類的析構函數,它的惟一做用就是在刪除對象(第 53 行代碼)後釋放已經分配的內存。
函數名是標識符的一種,原則上標識符的命名中不容許出現~
符號,在析構函數的名字中出現的~
能夠認爲是一種特殊狀況,目的是爲了和構造函數的名字加以對比和區分。
注意:at() 函數只在類的內部使用,因此將它聲明爲 private 屬性;m_len 變量不容許修改,因此用 const 限制。
C++ 中的 new 和 delete 分別用來分配和釋放內存,它們與C語言中 malloc()、free() 最大的一個不一樣之處在於:用 new 分配內存時會調用構造函數,用 delete 釋放內存時會調用析構函數。構造函數和析構函數對於類來講是不可或缺的,因此在C++中咱們很是鼓勵使用 new 和 delete。ios
析構函數在對象被銷燬時調用,而對象的銷燬時機與它所在的內存區域有關。不瞭解內存分區的讀者請閱讀《C語言和內存》專題。
在全部函數以外建立的對象是全局對象,它和全局變量相似,位於內存分區中的全局數據區,程序在結束執行時會調用這些對象的析構函數。
在函數內部建立的對象是局部對象,它和局部變量相似,位於棧區,函數執行結束時會調用這些對象的析構函數。
new 建立的對象位於堆區,經過 delete 刪除時纔會調用析構函數;若是沒有 delete,析構函數就不會被執行。
下面的例子演示了析構函數的執行。程序員
#include <iostream> #include <string> using namespace std; class Demo{ public: Demo(string s); ~Demo(); private: string m_s; }; Demo::Demo(string s): m_s(s){ } Demo::~Demo(){ cout<<m_s<<endl; } void func(){ //局部對象 Demo obj1("1"); } //全局對象 Demo obj2("2"); int main(){ //局部對象 Demo obj3("3"); //new建立的對象 Demo *pobj4 = new Demo("4"); func(); cout<<"main"<<endl; return 0; }
運行結果:
1
main
3
2數組
本帖原文地址:函數
http://c.biancheng.net/cpp/biancheng/view/196.htmlspa