這篇文章主要介紹了C++析構函數怎么使用的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇C++析構函數怎么使用文章都會有所收獲,下面我們一起來看看吧。
析構函數是特殊的成員函數
特征如下:
析構函數名是~類名;
無參數無返回值;
一個類有且只有一個析構函數;
對象聲明周期結束,編譯器自動調用析構函數;
class Stack { public: Stack(int capacity = 4) : _size(0), _capacity(capacity), _p(new int[_capacity]) { cout << "Stack(int capacity = 4)" << endl; } ~Stack() { cout << "~Stack()" << endl; if (_p) { delete[](_p); _p = nullptr; } _size = _capacity = 0; } private: int _capacity; int _size; int* _p; }; int main() { Stack s; return 0;//程序結束,調用s的析構函數 }
輸出:
class String { public: String(const char* str = "songxin") { cout << "String(const char* str = \"songxin\")" << endl; _str = (char*)malloc(strlen(str) + 1); strcpy(_str, str); } ~String() { cout << "~String()" << endl; free(_str); _str = nullptr; } private: char* _str; }; class Person { public: Person() : _age(20), _name() { cout << "Person()" << endl; } ~Person() { cout << "~Person()" << endl; } private: String _name; int _age; }; int main() { Person p; return 0; }
輸出:
析構函數在程序即將結束時,調用了Person的析構函數,在Person類的析構函數即將結束接著調用String類的析構函數。
歸納一下:
析構函數是與構造函數執行相反的操作的,構造函數負責給對象成員變量初始化并加載資源,而析構函數則是給對象的成員變量清理資源,而不是清理對象本身。
編譯器默認生成的析構函數能做些什么工作呢?我們前面已經介紹了編譯器生成的構造函數會去只會處理自定義類型的成員變量,那么析構既然和構造相對應,析構也應該是只去處理自定義類型的成員變量吧,確實如此,析構函數不會對內置類型有任何處理,只會在調用自身的析構后再去調用自定義類型成員的析構。
關于編譯器自動生成的析構函數,下面的程序我們會看到,編譯器生成的析構函數,會對自定類型成員調用它的析構函數。
class String { public: String(const char* str = "songxin") { cout << "String(const char* str = \"songxin\")" << endl; _str = (char*)malloc(strlen(str) + 1); strcpy(_str, str); } ~String() { cout << "~String()" << endl; free(_str); _str = nullptr; } private: char* _str; }; class Person { public: Person() : _age(20), _name() { cout << "Person()" << endl; } private: String _name; int _age; }; int main() { Person p; return 0; }
輸出:
默認生成的析構函數對成員變量的處理
內置類型不處理;
自定義類型成員調用相應的析構函數;
那成員變量中的內置類型處不處理其實都無所謂嘛,反正都要歸還給操作系統,但是有例外:
如果成員變量含有指針,并且指針指向一塊我們正使用的空間,指針也是內置類型,那如果不釋放指針指向的那塊空間就會造成內存泄漏,而編譯器生成的析構函數是不會處理此情況的,因為需要我們在析構函數中主動釋放內存,也就是說需要我們顯式的去定義析構函數。
class Stack { public: Stack(int capacity = 4) : _size(0), _capacity(capacity), _p(new int[_capacity])//使用new去申請內存 { cout << "Stack(int capacity = 4)" << endl; } ~Stack() { cout << "~Stack()" << endl; if (_p) { delete[](_p);//釋放內存 _p = nullptr; } _size = _capacity = 0; } private: int _capacity; int _size; int* _p; }; int main() { Stack s; return 0;//程序結束,調用s的析構函數 }
析構函數無論是我們顯式定義的還是編譯器生成的,都會在對象的聲明周期結束時自動調用,并且會調用自定義類型成員變量的析構函數來釋放資源,而對內置類型不做處理。
可以不顯式定義析構函數的情況
類的成員都是自定義類型的;
類的成員都是非指針的內置類型;
成員有指針,但并沒有管理內存資源;
如果類的成員變量有指針類型,并且我們讓指針指向了一塊動態分配的空間,那么就需要我們自己寫析構函數了。
總結:不是類直接管理另一塊內存資源的,就不需要寫析構函數,編譯器自己生成的就能處理。
關于“C++析構函數怎么使用”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“C++析構函數怎么使用”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。