1 #include<iostream> 2 using namespace std; 3 4 class Object{ 5 void* data; 6 const int size; 7 const char id; 8 public: 9 Object(int sz, char c) :size(sz),id(c){ 10 data = new char[size]; 11 cout << "Constructor Object" << id << ",size=" << size << endl; 12 } 13 ~Object(){ 14 cout << "Destructing object" << id << endl; 15 delete[]data; 16 } 17 18 }; 19 20 int main(){ 21 Object* a = new Object(40,'a'); 22 delete a; 23 void* b = new Object(41,'b');//會調用構造函數 24 delete b;//不會調用析構函數 25 26 return 0;
}
首先我們來開一下這個類的內存模型。
在運行結果截圖中,我們看到
Object* a = new Object(40,'a');
delete a;
可以正確的構造對象,在析構函數中也可以把用delete把data指針指向的內存釋放掉。(在對void*類型的內存使用delete,並不會發生錯誤,僅僅是把內存釋放掉。)但是在main函數中,我們看到delete知道它所操作的對象的類型是十分重要的。我們看到
void* b = new Object(41,'b');//會調用構造函數 delete b;//不會調用析構函數
在用delete刪除b的操作中,我們只是對b指向的對象進行了釋放,並沒有調用構造函數,也就是說data指向的內存並沒有被釋放,而此時又沒有指針指向剛才data指針指向的內存,從而造成了內存的丟失,更會造成內存的泄露。
這會有一個比較有意思的地方就是如果寫下面的代碼,
Object* pc=(Object*)malloc(sizeof(Object));//這個事情我們在new delete運算符與malloc free庫函數的區別中講到過,這時候不會調用構造函數,只會分配內存
delete pc;//而這句話因為pc是有類型的,不是void*所以會調用析構函數