2009-09-01 70 views
2

C++如何確保爲堆棧指定的對象調用析構函數?碰巧的析構函數(或它的指針),當我分配動態內存,如下內容:什麼是堆棧分配對象調用析構函數的機制?

class MyClass { 
public: 

    ~MyClass() 
    { 
    std::cout<<"Destructor called."<<std::endl; 
    } 

    MyClass() 
    { 
    std::cout<<"Constructor called."<<std::endl; 
    } 

}; 

.................................................................... 

//Limit scope for example 
{ 
    MyClass instance; 
} 

構造函數和析構函數都被調用。這裏發生了什麼?

+0

實例對象的名稱。 instance()只是對類的無參數ctor的調用。在這種情況下,parens是不必要的,但它肯定不是對稱爲instance()的方法的調用。 – dicroce 2009-09-01 13:02:07

+5

我沒有看到任何動態內存分配。 – 2009-09-01 19:54:34

回答

7

編譯器將適當位置的對象的析構函數插入到析構函數中。

1

構造函數被調用是因爲你正在創建一個對象。調用析構函數是因爲你清理了那個對象。請記住,在C++中,堆棧中聲明的對象在其包含的作用域消失時會自動清理。

3

只要創建變量,就會調用構造函數。至於析構函數,編譯器在範圍的末尾發出代碼來調用析構函數。爲了感受這一點,可以嘗試使用'goto'或switch/case結構過早退出範圍,並觀察編譯器的抱怨。

+1

「創建變量後立即調用構造函數。」那麼,當構造函數被調用時,對象創建就會發生,所以這並不奇怪。變量OTOH的內存可能會提前提供。 – sbi 2009-09-01 13:47:01

+1

據我所知,你可以用goto退出範圍,編譯器仍然知道該對象超出範圍。你不允許做的是用goto/switch跳過對象聲明(構造)。 – UncleBens 2009-09-01 14:11:03

+0

@UncleBens:使這個「對象定義」,但否則你是對的。 (我讀得很快,甚至沒有在Managu的回答中看到這個錯誤。) – sbi 2009-09-01 17:13:26

3

是的,構造函數和析構函數都被調用。更重要的是:

{ 
MyClass instance; 
throw "exception"; 
} 

在這個例子中,析構函數也被調用。這就是爲什麼我總是喜歡在堆棧上分配我的對象(或者至少用一個堆棧分配的監護人包裝動態分配)。

4

你不會知道爲什麼這

{ 
    int i; 
} 

自動創建並銷燬i,你會嗎? C++做了很多事情來允許你創建類似於內置類型的類型。就如同內置的類型,在C++(除,也就是說,Java或C#),這

{ 
    MyClass instance; 
} 

並不僅僅定義可以綁定到null或一些實際的對象的引用。它創建了一個實際的對象。

對象創建分兩步進行:首先(在進入作用域時)提供原始內存。然後(當遇到對象定義時)構造函數被調用。對於內置類型,不調用構造函數。如果你不初始化一個內置變量,它有一個隨機值。 (實際上它是在步驟#1中提供的內存中的任何位模式)。對象刪除也分爲兩步:首先,調用析構函數(不是內置函數),然後將內存返回給運行時系統。

(請注意,提供和刪除堆棧變量內存通常是incementing /遞減寄存器便宜。)

0

那麼,它不只是構造後調用析構函數。
當它即將終止程序時調用它。

int main() { 
    MyClass obj; 
    cout<<"testing....1"<<endl; 
    cout<<"testing....2"<<endl; 
    return 0; 
} 

答:

Constructor called. 
testing....1 
testing....2 
Destructor called. 
+1

當程序即將終止時,它不會調用析構函數。堆棧對象超出範圍時調用析構函數。因爲你主要是這樣做的,所以這兩者恰好相吻合。 – 2009-11-05 07:15:09

相關問題