2010-05-02 120 views
14

我注意到,有兩種方法可以創建C++對象:創建C++對象

BTree *btree = new BTree; 

BTree btree; 

從我所知道的,唯一不同的是類對象是如何訪問( 。 - > - >運算符),並且當使用第一種方法時,私有整數被初始化爲0.

哪種方式更好,有什麼區別?

你怎麼知道什麼時候使用一個或另一個?

+3

請參閱此處瞭解有關堆棧和堆棧的信息:http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap,http://stackoverflow.com/questions/ 408670/stack-static-and-heap-in-c – 2010-05-02 00:59:20

回答

0

好吧,它們被儲存在不同的記憶區域。

這是一個很好的閱讀。 Heap and Stack

+0

我對堆和堆棧有所瞭解。爲什麼我會在乎它放在哪裏?我什麼時候需要它在堆中,什麼時候我需要它在堆棧中? – neuromancer 2010-05-02 00:56:09

+0

堆棧在應用程序中受到限制。堆沒有限制(虛擬內存空間)。堆棧也受限於變量的範圍。堆允許您傳遞結構而不考慮範圍。 – 2010-05-02 00:57:46

+0

這種說法是錯誤的。請不要忽略靜態內存。例如。全局(或命名空間範圍)中的'BTree btree;'語句在靜態內存中創建對象,這可能很有意義,特別是在內存受限的環境中(所有那些自動內存管理的語言,如Java *咳嗽*似乎都是盲目的我們..)。 – Frunsi 2010-05-02 01:13:59

5

第一種形式在堆上創建對象,而第二種形式在堆上創建對象。

當功能完成運行時,第二個將被銷燬。 第一個將保持活着,直到被刪除。

如果您只想使用當前範圍內的對象,則第二種形式最好。你不必擔心擺脫它,因爲它會爲你完成。另請注意,如果在堆棧上創建了類,某些庫不起作用。

如果對象應該超過該功能,則新窗體是更好的選擇。

32

兩個差異:

  • 它們在存儲器中創建的不同部分中的對象(堆VS堆棧)

  • 對象壽命是不同的: 在第一種情況中,代碼管理內存分配明確,,它也必須明確地管理取消分配(使用刪除/刪除[])。

    在第二種情況下,該對象被自動地在其閉合範圍的端部釋放(或者一種方法,一種方法內的嵌套塊,或一類),你使用哪一個

主要取決於在對象的生命週期中(如果它應該超過創建它的方法)。

+1

+1,我只想添加第一條和簡單的經驗法則:喜歡自動分配,在需要時使用顯式分配,例如,一個壞例子:'void foo(){BTree * btree = new BTree; btree-> DoSomething的();刪除btree; }' – Frunsi 2010-05-02 01:08:56

+0

如果該對象在main中聲明,當兩個方法的main都退出時它會自動被釋放嗎? – neuromancer 2010-05-02 01:32:28

+0

在程序結束之前未被刪除的堆分配對象(使用'new')本身不會被「解除分配」。例如,它的析構函數將不會因程序結束而被調用。但是,該對象使用的內存將返回到操作系統。在現代操作系統下運行的程序無法在退出後繼續使用內存,無論它有多嚴重的泄漏。 – 2010-05-02 01:50:53

2

高級別區別是對象生存期。例如,如果您正在編寫視頻遊戲,您將通過new分配與堆上的怪物對應的對象。這樣,怪物的基礎物體就像怪物一樣生活,這在編寫程序時是不可知的。當玩家殺死怪物時,你的代碼可以使用delete銷燬怪物物體。

另一方面,您將使用另一種形式的總分計數器,因爲您知道計數器需要多長時間(大概只要遊戲正在運行!)。通過將這種形式放在任何函數體外的「全局範圍」中,它將被靜態分配,作爲程序二進制本身的一部分。

最後,如果你計算數組的總和,是這樣的:

int mysum(int* arr, int len) { 
    int sum = 0; 
    for (int i = 0; i < len; ++i) { sum += arr[i] } 
    return sum; 
} 

sum變量堆棧,這基本上是你想要什麼就分配:你不要臨時變量必須顯式釋放,並且只在該函數實際運行時纔會執行。

3

這兩種形式的另一個區別是分配這些對象的存儲時間。表格BTree bTree;命名爲靜態分配,其分配在編譯時完成 - 即編譯器將在運行時爲內存中的此對象安排內存空間。而所謂的動態分配BTree *pbTree = new BTree的分配 - 在運行時執行 - 即只有當正在運行的程序到達此點時纔會分配momory。

在這種情況下,靜態和動態分配之間的差異並不明顯。考慮以下情況:需要爲整數數組分配內存空間,但是隻能在運行時確定元素的數量,即我們只能知道程序開始執行後數組所佔用的確切內存空間。

// in this function, we want to return a copy of the parameter array 
int *array_cpy(int *arr, int num){ 
    int *copy = new int[ num ]; 

    int i; 
    for(i = 0; i < num; i++){ 
     copy[ i ] = arr[ i ]; 
    } 

    return copy; 
} 

這裏定義int copy[ num ];是不恰當的,其中一個原因是我所上述,另一種是copy壽命活得比的功能。但是,鑑於最近的語言規範允許VLA,第二個原因是這個問題的關鍵。

3

在你是應該堆棧還是堆分配內存之間進行選擇時,你需要仔細研究兩者之間的差異。

是的,堆棧內存具有在超出範圍時自動釋放的優點,但通過智能指針和堆分配也可以實現同樣的效果。更重要的是爲什麼發生這種情況的原因。

性能: 堆棧內存被自動清除,因爲它涉及內存超出範圍時棧指針的簡單移位。由於這個原因,堆棧內存的分配和釋放比堆內存快得多。

內存使用期限: 堆分配內存超出了分配函數的範圍。堆棧不是。從上面關於調整堆棧指針的推理出發,一旦內存被解除分配,它是空閒的並且很可能被覆蓋以用於下一個堆棧分配。

簡而言之,當分配是臨時的時候使用堆棧內存,特別是如果您需要重複分配並且性能很重要。當對象需要超出分配方法時使用堆內存。