2011-09-29 69 views
1

可能重複:
Does this type of memory get allocated on the heap or the stack?內存管理,協議棧和堆問題

我有一些記憶有關的問題,我希望你們會能夠回答。考慮以下代碼,以表示,有很多原始數據成員的方法和大量的一大類:

class Foo { 
    public: 
    Foo() : // Initialize all data members ... 
     { } 

    // Lots of methods ... 

    ~Foo() { /*Nothing needed here ... correct?*/ } 

private: 
    int a; 
    int b; 
    char c; 
    double d; 
    // Lots of other primitive data members (no pointers) ... 
}; 

class Bar { 
    public: 
    void func() { 
     foo = new Foo(); 
    } 

    // Assuming Bar::func() is always called before deletion ... 
    ~Bar() { delete foo; } 
    private: 

    Foo* foo; 
}; 

int main() { 
    Bar bar; 
    bar.func(); 

    Bar* barptr; 
    barptr->func(); 

    return 0; 
} 

我的問題是,當我打電話bar.func(),都在分配的Foo所有的數據成員棧內存或內存(我知道foo會堆在...我想!)?當我打電話給barptr->func()時呢?例如,Foo::a在堆棧上還是在堆上?

此外,我是否需要明確刪除Foo::~Foo()中的任何內容? Foo只有原始本地數據成員,並且沒有任何功能使用newmalloc()

在我完全不知道我在說什麼的情況下,如果有人能夠解釋這些數據的存儲位置,我將不勝感激。

+0

@sehe:我懷疑它是微軟文本表示的產物。 – wallyk

+0

另請參見:http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization描述了爲什麼當C++完成正確時,析構函數通常是空的。 –

+0

@sehe:你確定嗎?這種現象不會發生在我的基於Linux的瀏覽器的複製和粘貼操作上,但偶爾會發生在Windows上。不知道爲什麼它每次都沒有發生 - 也許有一些內部的黑客來解決它。 – wallyk

回答

4

一切避免這種情況。行foo = new Foo();在堆上創建Foo(包括全部其成員)。
只有命名對象在堆棧上。在你的情況bar(一個Bar)和barptr(指向Bar的指針)。 Foo s析構函數不需要做任何事情,這實際上很常見,如果你正確使用RAII,就像是C++的方式。

在你main功能,bar是堆棧是一個Bar,其分配在堆上一個Foo上的區域。如果barptr;實際被初始化,barptr將是堆棧上的某個區域,它指向某個地方的Bar(可能堆棧可能不是)。但是,在任何情況下,Bar s foo成員將被分配在堆上,因爲這是構造函數告訴它執行的操作。

main函數中,bar是堆棧上的一個區域(指向(大型基元集合)的指針),它在堆上分配(大量基元)。
如果barptr;實際上被初始化了,barptr將是堆棧上的一個區域,它指向一個指向(一個(大量原語集合)指針的指針)(可能堆棧可能不是)。然而,在任何情況下,(堆的大量原語)都將被分配到堆上,因爲這就是構造函數告訴它做的事情。

因爲我知道有人會提到它,堆/堆棧的區別在於編譯器的意外,而不是以任何方式標準化。如果感覺像這樣,它完全被允許「欺騙」並把東西放在其他地方。例如,全局對象通常不在堆棧或堆中,而是在另一個地方。而且,這就是C#和Java如此快速的運行,儘管頻繁(明顯)使用內存管理。編譯器經常「欺騙」並將「動態範圍」對象放入堆棧。

+0

感謝您的非常詳細的迴應!非常感激! – Zeenobit

1

當您調用新的Foo()時,您正在堆上創建一個新的Foo對象。

Foo中的所有基元數據成員都存儲在Foo對象中。因此,它們也在堆上 - 在Foo對象中。

您的Foo析構函數不需要顯式地處理原始數據成員。也不需要明確處理類的成員;他們的析構函數會在Foo的析構函數後自動調用。

一個具有指向動態分配內容的裸指針的類通常需要在析構函數中使用顯式語句來處理某些內容。您可以通過使用智能指針像new在堆上,包括它的所有成員分配std::auto_ptrboost::shared_ptr.