創建對象有以下四種形式:
#include <iostream> using namespace std; class A{ private: int i; public: A(){ cout<<"調用沒有參數的構造函數"<<endl; } A(int a):i(a){ cout<<"調用有一個參數的構造函數"<<endl; } ~A(){cout<<"成員變量為:"<<i<<"\t調用析構函數"<<endl;} }; void main(){ A a0; //形式一:直接聲明一個對象 A a1(1); //形式二:隱式調用A帶一個參數的構造函數 A a2 = A(2); //形式三:顯式調用A帶一個參數構造函數 A *p = new A(3); //形式四:動態分配 }形式一:實際上等同於 A a0 = A();調用不帶參數的構造函數進行對象的創建
形式二:實際上等同於 A a1 = A(1);調用帶一個參數的構造函數進行對象的創建
形式三:與形式二相同,這三種形式其實都是按照參數調用對應的構造函數在棧中創建對象,使用完畢后,系統自動回收對象內存,無需手動釋放。
形式四:在堆內存中動態開辟空間創建對象,需要手動釋放內存。
形式四:在堆內存中動態開辟空間創建對象,需要手動釋放內存。
還有一點需要注意“A a3();”編譯和運行都沒有問題,但是並沒有創建對象
運行結果:

由圖可以得出如下結果:
(1)創建對象需要調用對應的構造函數,釋放對象需要調用析構函數。因為形式一對應的構造函數沒有對對象進行初始化所以成員變量i出現隨機數“-858993460”.
(2)析構的順序與構造順序相反,上面代碼中構造順序是a0,a1,a2 ;析構順序是a2,a1,a0.
(3)在棧中創建的對象無需手動釋放,系統自動回收。在堆中創建的對象需要手動釋放。在運行結果中調用了4次構造函數,然而析構函數只執行了3次,沒有釋放指針p所指向的對象。在上面程序末尾加入代碼delete p;p=NULL;運行結果如下:

堆中的對象也被刪除了。
但需要注意的是delete p;只是釋放了內存空間,指針p仍然指向那塊空間,所以一定要將p指針置為NULL;
#include <iostream> using namespace std; class A{ private: int i; public: A(){ cout<<"調用沒有參數的構造函數"<<endl; } A(int a):i(a){ cout<<"調用有一個參數的構造函數"<<endl; } ~A(){cout<<"成員變量為:"<<i<<"\t調用析構函數"<<endl;} }; void main(){ A a0; //方法一:直接聲明一個對象 A a1(1); //方法二:隱式調用A帶一個參數的構造函數 A a2 = A(2); //方法三:顯式調用A帶一個參數構造函數 A *p = new A(3); //方法四:動態分配 delete p; cout<<"delete后指針p指向的空間:"<<p<<endl; p=NULL; }運行結果如下:

還需要注意的一點是,delete不能釋放棧中的空間。我曾經犯過一個錯誤,錯誤代碼如下:
#include <iostream> using namespace std; class A{ private: int i; public: A(){ cout<<"調用沒有參數的構造函數"<<endl; } A(int a):i(a){ cout<<"調用有一個參數的構造函數"<<endl; } ~A(){cout<<"成員變量為:"<<i<<"\t調用析構函數"<<endl;} }; void main(){ A a(1); A *p1 = &a; delete p1; //希望釋放棧中的對象 }編譯沒有問題,但運行出錯。

所以delete一定要和new成對出現,delete釋放的是動態開辟的內存。棧中的內存不需要咱們去釋放,系統自己會回收。
如果構造函數有默認參數,則可能出現不知道調用哪個構造函數的問題
#include <iostream> using namespace std; class A{ private: int i; public: A(){cout<<"調用沒有參數的構造函數"<<endl;} A(int a = 0):i(a){ cout<<"調用有一個參數的構造函數"<<endl; } }; void main(){ A a0; }編譯器不知道該調用哪一個構造函數,所以刪除其中一個構造函數即可。