(筆記):構造函數與析構函數
一、構造函數與析構函數
C++ 在類中的成員變量不能直接用 需要自己將變量所占的內存地方清零,否則直接用的話 除了賦值外都可能使程序出錯,因此為了不讓這種情況的發生,C++中專門設計了一種Constructor構造器 即構造函數 與類名相同 無返回類型。而析構函數就是做"清理善後"工作。在超過類的實例的Scope範圍,系統就會自動調用該函數。簡單來說在構造函數中又有默認構造函數(無參數)和自己定義的構造函數(有參數)之分。拷貝構造函數暫且不說明。下面通過一段代碼,及其代碼上所指示的標註對構造函數和析構函數的具體使用所一個簡單說明,程序源碼如下(點開即可)(代碼中標註 (1)(2)(3)這樣的序號 在註釋區會有詳細的解釋
1 #include<iostream> 2 using namespace std; 3 class X{ 4 5 public: 6 int x; 7 int *p; 8 X(){} //(1) 9 X(int y);//(2) 10 ~X(); //(3) 11 }; 12 X::X(int y) //註意這裏沒有void 的返回類型 因為析構和構造函數都沒有返回類型 13 { 14 p =new int;//申請資源 (4) 15 x = y; //這實際上稱為賦值 而不是初始化View Code16 cout<<"進入構造函數了其值為:"<<x<<endl; 17 } 18 X::~X() 19 { 20 delete p;//釋放資源 21 //(5) 22 cout<<"進入的是變量值為 "<< x<<"的析構函數" <<endl;//可以看出退出構造函數的順序 23 } 24 int main() 25 { 26 X a(12);//此時將12給了構造函數的形式參數 27 28 { 29 cout<<"進入變量b的scope"<<endl; 30 X b(10); 31 cout<<"退出變量b的Scope"<<endl; 32 } 33 34 return 0; 35 }
註釋區:
(1)這樣的才是默認構造函數,如果我們沒有顯示定義構造函數,則編譯器就會提供一個默認構造函數稱為合成的默認構造函數
(2)構造函數 在實例化的時候自動調用 //註意這裏已經不是默認構造函數了
(3)析構函數 在這個類超出scope前 自動調用
(4)可以再構造函數中申請空間 之後再析構函數中釋放掉
(5)//這裏可以對一些申請的內存資源進行釋放 進行操作
//比如delete p 或者delete[]p 這裏的P是在構造函數中申請的
註意:
// new int ;
// new int *;
// new int *[10];
// delete p;
// delete[]p; //記住 僅僅new[]時(代表數組形式)才會用這個帶括號的(下面的筆記圖片中有記載)
試驗結果:
結果說明:
定義一個變量的時候,系統會自動的調用構造函數,超出變量的scope範圍的時候,系統也會自動的調用析構函數。
補充說明:
如果在以上的代碼基礎上 ,在main函數中 改為下面的圖片,則在編譯的時候不會出錯,但是運行的時候就會出錯。是因為沒有調用其他的析構函數導致的程序崩潰。但是在類X聲明的內部,構造函數中new 一個數組形式的內存和在析構函數中delete p這樣的形式不會出現錯誤,因為delete會刪除p指向的那塊內存,不涉及析構函數,所以不會出現錯誤。具體請看下面的總結
總結:對上面的delete p和delete[]p做的筆記,如下圖所示:
(筆記):構造函數與析構函數