2013-08-07 77 views
2

我在我的代碼中使用了額外的括號。我想,當局部變量的作用域結束後析構函數應該叫,但它並沒有這樣的工作:C++:爲什麼它不調用析構函數?

class TestClass { 
public: 
    TestClass() { 
     printf("TestClass()\n"); 
    } 
    ~TestClass() { 
     printf("~TestClass()\n"); 
    } 
}; 

int main() { 
    int a, b, c; 
    { 
     TestClass *test = new TestClass(); 
    } 
} 

它輸出:

識別TestClass()

所以它不調用TestClass的析構函數,但爲什麼?如果我手動調用它(刪除測試),它會調用析構函數,對。但是爲什麼它不在第一種情況下調用析構函數?

+1

因爲如果你創建了一個對象與'new',它只能調用'它delete'時破壞 - 它不會被走出去的範圍被破壞。 – Nbr44

+2

@ Nbr44:不完全正確。你可以直接調用析構函數。當然,這不會釋放內存,但會破壞對象。然後,沒有未定義行爲的情況下正確釋放內存的唯一方法是在其位置構建另一個相同類型的對象(通過放置新的對象)並調用delete。 –

回答

12
TestClass *test = new TestClass(); 

您使用new創建一個動態分配的對象(最有可能放在堆上)。此類資源需要由您管理的手動。通過管理,完成使用後,您應該使用delete

{ 
    TestClass *test = new TestClass(); 
    // do something 
    delete test; 
} 

但是對於大部分的目的和意圖的,你只需要使用自動存儲對象,從而釋放您不必手動管理對象的麻煩。它也很可能會有更好的表現,尤其是對於短命的對象。 除非你有充分的理由不這樣做,否則你應該總喜歡使用它們。

{ 
    TestClass test; 
    // do something 
} 

但是,如果你需要動態分配對象的語義或指針,它總是會更好地使用一些機制來封裝對象/資源對你來說,這也提供了刪除/釋放尤其是當您使用例外和條件分支時您更加安全。在你的情況下,如果你使用std::unique_ptr會更好。

{ 
    std::unique_ptr<TestClass> test(new TestClass()); 
    // auto test = std::make_unique<TestClass>(); in C++14 

    // do something (maybe you want to pass ownership of the pointer) 
} 


以下是相關鏈接,以幫助你決定是否要使用自動存儲對象或動態分配的對象: Why should C++ programmers minimize use of 'new'?

+1

「除非你有一個非常好的理由不這樣做,否則你應該總喜歡使用它。」 - 但爲什麼這裏不使用指針非常重要?因爲你可能忘記刪除它或其他一些重要的原因? – JavaRunner

+1

@JavaRunner是的。而且他們最容易出錯,會給你帶來不必要的間接性,這可能會影響性能,而且在代碼上加上大量的''''和''''''就很難看。 –

+2

@JavaRunner另外一個問題,除了陰雲密佈的生命週期外,還有一個問題:擁有一個指向動態分配對象的指針,也就是負責刪除它的對象會變得很難。價值語義比引用語義更容易推理。 – juanchopanza

8

因爲你有一個指向動態分配對象的指針。只有指針超出了範圍,而不是它指向的對象。您必須在指針上調用delete才能調用指針的析構函數。

嘗試用一個自動存儲對象,而不是:

{ 
    TestClass test; 
} 

這裏,析構函數被在離開範圍調用。

在C++中使用原始指針來動態分配對象是不鼓勵的,因爲它很容易導致資源泄漏,如代碼示例中所示。如果真的需要指向動態分配對象的指針,那麼用smart pointer來處理它們是明智的,而不是試圖手動處理它們的銷燬。

1

This answer是不夠好,但我想補充一些。

我看到你已經編碼爲Java。在C++中創建堆棧變量/對象關鍵字new不是必需的。其實當你使用關鍵字new你的對象是在堆中創建的,它不會在離開範圍後破壞。要消滅它,你需要調用delete你的情況delete test;

在這樣的結構是你的,剩下範圍你只失去指針後所點到的對象,所以在離開範圍後,將無法釋放內存,並調用析構函數,但最終OS在執行exit()指令後立即調用析構函數。

綜上所述C++ = Java

相關問題