2016-12-27 56 views
4

我知道,當爲您提供隱式構造函數時,您的類成員將從左到右和從上到下進行初始化。換句話說,按照他們聲明的順序。然後,當類對象超出範圍時,所有成員都以相反的順序被破壞。但是,如果我必須自己銷燬成員,我是否必須按照列出的順序來執行操作?例如:我是否必須按順序明確銷燬對象

struct Dog {}; 

struct Animal 
{ 
    Dog* dog1 = new Dog; 
    Dog* dog2 = new Dog; 
    ~Animal() 
    { 
     delete dog2;  // First delete dog2 
     delete dog1;  // Then delete dog1 
    // Or do I? 
    } 
}; 

我認爲所提供的析構函數是空的。因此,當我聽到類在超出範圍時會調用它的析構函數時,它不會在它自己的析構函數中執行此操作,而是在它之後使用編譯器單獨生成的代碼執行此操作。因此,例如:

struct Animal 
{ 
    Dog dog1; 
    // ~Animal(){}implicitly defined destructor here. dog1 isn't destroyed here 
    // But is destroyed here, or after, or something along those lines with separate code that the compiler generates? 

}; 

感謝。

回答

3

請記住,刪除指針指向的對象和銷燬指針本身是有區別的。當包含對象的生命週期結束時,C++將自動銷燬指針本身,並且它將按照它們構建的順序相反的方式進行操作。根據對象的設置方式,您可以根據需要隨意刪除這些指針。作爲一個說明,如果您從使用原始指針改爲unique_ptr s,那麼這將完全爲您處理,並且根本不需要甚至有一個析構函數!

5

但是,如果我必須自己銷燬成員,我必須按照它們列出的確切順序來執行操作嗎?

不,不管你喜歡什麼樣的順序。

但我更喜歡匹配「自動」順序,以免被驚訝。

我認爲提供的析構函數是空的。因此,當我聽到類在超出範圍時會調用它的析構函數時,它不會在它自己的析構函數中執行此操作,而是在它之後使用編譯器單獨生成的代碼執行此操作。

基本上,是的。

執行析構函數體是破壞的一部分。另一部分是破壞所有成員和基地。

+0

我明白了。我開始認爲反向破壞只對棧上的東西很重要,而不是堆?我錯了嗎?編輯:沒有等待,但可以在堆上創建類對象。哦,我很困惑。 – Zebrafish

+0

@TitoneMaurice:取決於「重要」的含義。 –

+0

@TitoneMaurice - 總是很重要,特別是如果成員是彼此相關的對象。你不想以錯誤的順序摧毀那些人。 – StoryTeller

1

您在析構函數中銷燬對象的順序通常無關緊要,除非有某些原因應該基於對象擁有的資源需求。例如,如果要刪除擁有的線程對象,則可能需要確保在刪除線程可能使用的項目之前線程已經退出。 shared_ptr和其他智能指針在這些情況下很有用。它們也有助於減少對一般析構函數的需求。

1

正如軌道上的輕度賽跑所回答的,您可以按照任何順序來摧毀班級成員。但是,默認的析構函數(如果沒有明確地調用)總是遵循特定的順序來銷燬與創建的成員順序相反的成員。

由於析構函數也是一個函數,所以可以在該函數中添加語句以便在對象的銷燬時執行。然後,析構函數將執行這些語句,然後它將按照相反的順序刪除類的成員。

例如:

struct Dog {}; 

struct Animal 
{ 
    Dog* dog1 = new Dog; 
    Dog* dog2 = new Dog; 
    int var; 

    ~Animal() 
    { 
     delete dog1;  // First delete dog1 
    } //delete var and then delete dog2 
}; 

析構函數將執行它的身體,然後,它會開始刪除它的其餘成員以相反的順序。