1. 程式人生 > >腳踏實地,用心編寫出客戶滿意的程式碼,為公司創造出應有的價值。

腳踏實地,用心編寫出客戶滿意的程式碼,為公司創造出應有的價值。

首先需要指出的是,我們通常用“堆”和“自由儲存”這兩個術語來區分兩種不同型別的動態分配記憶體。

1.常量資料:常量資料區域主要用於儲存字串以及其他在編譯期就已經知道值的資料。例項化的物件是不能儲存在 這 個區域中的。

在程式的整個生存期內,這個區域中的所有資料都是有效的。而且,所有這些資料都是隻讀的,如果對這些資料進行修改,其結果在C++中是沒有定義的。造成這種後果的部分原因是編譯器可能會對常量數據的基本儲存格式進行任意優化。例如,在某個特定的編譯器中,可能會將字串常量儲存在重疊物件內以進行優化。   

2.棧:在棧中儲存的是自動變數。自動變數在定義的時候被立即構造,並且在自動變數作用域結束的時候被立即銷燬

,因此程式設計師無法對已經分配但尚未初始化的棧空間直接進行操作(除非你有意識地使用顯示解構函式和布局new語法)。

棧記憶體的分配通常要比動態記憶體的分配(堆和自由儲存)快很多,因為每次棧記憶體的分配只涉及棧指標的自增操作,而無需進行更為複雜的記憶體管理。

3.自由儲存:自由儲存時兩種動態記憶體區域之一,它是通過new/delete來分別進行分配/釋放。

物件的生存期可能會小於所分配的儲存空間的生存期。也就是說,自由儲存區域中的物件在分配記憶體時並不要求立即進行初始化,而且在銷燬物件時,也不要求立即釋放記憶體空間。在儲存空間已經被分配但還沒有進入到物件生存期的這段時間內,我們可以通過一個void*型別的指標來訪問和操作這塊儲存空間

,但我們不能訪問物件中任何一個非靜態的成員或非靜態的成員函式,不能去獲得他們的地址,或者進行其他的操作。

4.堆:堆是另一種動態記憶體區域,它是通過malloc()/free()函式以及這些函式的其他形式來進行分配/釋放的。

我們要注意的是,儘管在某個特定的編譯器中,預設的全域性運算子new和delete可能會用函式malloc()和free()來進行實現,但是堆還是不同於自由儲存,在堆中分配的記憶體不能再自由儲存區域中被安全地釋放,反之亦然 在堆中分配的記憶體,可以用於物件的placement new構造過程 和顯示的析構過程中。如果是這種用法,那麼自由儲存區域中關於物件生存期的注意事項也同樣適用於堆。

5.全域性/靜態:在程式啟動的時候,這些變數/物件或靜態的變數/物件就已經被分配了儲存空間,但只有等到程式執行的時候,這些變數/物件才可以進行初始化。例如:函式中的靜態變數只有當程式第一次執行到變數的定義語句時才能被初始化。

對於跨越多個編譯單元的全域性變數,它們的初始化順序是未定義的,並且我們在管理全域性物件(包括類的靜態成員)之間的依賴性的時候要特別小心。通常來說,我們可以通過一個void*指標來對未初始化的物件儲存空間進行訪問和操作,但我們不能再物件的生存期之外來使用或者引用非靜態的成員變數或成員函式。

指導原則:我們應該優先使用自有儲存(new/delete),並且要避免去使用堆(malloc/free)。