2014-02-20 52 views
1
class A 
{ 
    public: 
    A() 
    { 
     std::cout << "I am ctor\n"; 
    } 
    ~A() 
    { 
     std::cout << "I am dtor\n"; 
    } 
    void printme() 
    { 
     std::cout << "I am printme\n"; 
    } 
}; 

int main() 
{ 
    A aobj; 
    aobj.printme(); 
    aobj.~A(); 
    aobj.printme(); 
    return 0; 
} 

這是輸出:C++:析構函數如何在內部工作以及誰調用默認析構函數?

$./testdtor 
I am ctor 
I am printme 
I am dtor 
I am printme 
I am dtor 

到析構函數顯式調用的行爲像一個正常的函數調用,一旦對象超出範圍,調用析構函數,但我想通過知道哪個實體?

+2

你是什麼意思, 「實體」?它由編譯器生成的代碼在對象作用域的末尾調用。 –

+0

是什麼讓你認爲一個「實體」稱爲析構函數?它只是生成的代碼的一部分。 – tenfour

+0

我想用「實體」OP意味着使用一個非常抽象的詞,而不是他認爲這樣的「實體」是他的程序代碼的一部分或者這樣......他的意思是「實體」足夠抽象以包含生成的程序集;) – leemes

回答

6

編譯器爲所有自動對象生成析構函數調用代碼。這些析構函數按照與對象構造順序相反的順序被調用。

delete話務員通話對象的析構駐留在該地址指向的對象由操作參數,並且通常與動態對象使用的(我想說總是)。

這種行爲允許可靠的內存管理和許多其他有用的技巧,我們非常喜歡C++

在那裏你可以在大多數情況下將手動調用析構函數的唯一情況是分配使用placement new操作對象時。

+3

爲了避免混淆,我會使用「自動」和「動態」而不是「堆棧」和「堆」。 –

0

內部析構函數是一種常用函數。它用於釋放一個類使用的資源,它可以有任何行爲。

調用析構函數是由編譯器生成的。它調用時:

1對象超出範圍

void foo() { 
    // Declare an instance of some object 
    MyClass object; 

    // code 

    // destructor for 'object' called here 
} 

2當刪除一個對象:刪除myPtr

3當刪除對象的數組:刪除[] myArray的

4如果拋出異常的析構函數被稱爲在範圍

所有對象有一個當析構函數不會被調用情況。如果在執行對象的構造函數中拋出異常並且在不被捕獲的情況下將其轉義,則此對象的析構函數將不會被調用。

+0

4是1和3的特殊情況,每個元素意味着2,所以我會將它們包裝在一起並在自動存儲中調用1 + 4對象的生命週期結束,以及2 + 3從動態生成對象的生命週期結束分配(通常)。 – leemes

6

這取決於對象在哪裏,它的生命是什麼。

  • 對於像您的示例的自動變量,通過代碼在其範圍
  • 對於靜態變量的端部產生的,通過由atexit機制稱爲代碼main結束
  • 對於線程局部變量之後,通過線程後類似的機制結束
  • 對於非靜態類成員變量或鹼子對象,通過含有它
  • 對於由new創建的對象的類的析構函數生成的代碼,通過由共同生成的代碼rresponding刪除表達
  • 對於通過投放新創建的對象,析構函數只能被顯式調用。