當一個C++對象被創建時,有兩件事會發生:
(1)爲對象分配內存.
(2)調用構造函數來初始化那個內存.
到目前爲止,我們應該確保步驟 2)一定發生。C++強迫這樣做是因爲未初始化的對象是程序出錯的主要原因。不用關心對象在哪裏創建和如何創建的—-構造函數總是被調用。
然而,步驟1)可以以幾種方式或在可選擇的時間內發生:
1) 靜態存儲區域,存儲空間在程序開始之前就可以分配。這個存儲空間在程序的整個運行期間都存在。
2) 無論何時到達一個特殊的執行點(左花括號)時,存儲單元都可以在棧上被創建。出了執行點(右花括號),這個存儲單元自動被釋放。這些棧分配運算內置在處理器的指令集中,非常有效。然而,在寫程序的時候,必須知道需要多少個存儲單元,以使編譯器生成正確的指令。
3) 存儲單元也可以從一塊稱爲堆(也可稱爲自由存儲單元)的地方分配。這稱爲動態內存分配,在運行時調用程序分配這些內存。我們也負責決定何時釋放內存。這塊內存的生存期由我們選擇決定—而不受範圍限制。
這三個區域經常被放在一塊連續的物理存儲單元裏:靜態內存、堆棧和堆(由編譯器的作者決定它們的順序),但沒有一定的規則。堆棧可以在某一特定的地方,堆的實現可以通過調用由運算系統分配的一塊存儲單元來完成。
當一個C++對象被銷燬時,會發生兩件事:
(1)調用析構函數.
(2)釋放內存.
下面通過一個例子:爲類重載new,delete ,爲數組重載new[], delete[] 來理解C++對象創建和銷燬的過程.(說明:當我們重載運算符時,編譯器爲優先使用)
#include <new.h>
#include<stdio.h>
#include<iostream.h>
class widget{
int i[10];
public:
widget(){
cout<<"*";}
~widget(){cout<<"~";}
void * operator new(size_t sz){
cout<<"widget::new: "<<sz<<" bytes"<<endl;
return ::new char[sz];
}
void operator delete(void *p){
cout<<"widget::delete"<<endl;
::delete p;
}
void * operator new[](size_t sz){
cout <<"widget::new[]: "<<sz<<" bytes"<<endl;
return ::new char[sz];
}
void operator delete[](void *p){
cout<<"widget::delete[]"<<endl;
::delete []p;
}
};
void main(){
cout<<"new widget" <<endl;
widget *w=new widget;
cout <<"/n delete widget"<<endl;
delete w;
cout<<"/n new widget[25]" <<endl;
widget *wa= new widget[25];
cout<<"/n delete []widget"<<endl;
delete []wa;
};
運行結果:
new widget
widget::new: 40 bytes
*
delete widget
~widget::delete
new widget[25]
widget::new[]: 1004 bytes
*************************
delete []widget
~~~~~~~~~~~~~~~~~~~~~~~~~widget::delete[]
Press any key to continue