簡體   English   中英

什么時候應該在C ++中使用自己的破壞函數?

[英]When should I use destruction function of my own in C++?

最近,我正在使用C ++研究OOP,在以下情況下應該使用自己的破壞函數時,我感到很困惑:

class T1{
private:
    int data;

public:
    T1(){...};
    ~T1(){}; // should I write my own function here?
};

class T2{
private:
    T1* pointer_to_T1;

public:
    T2(){...};
    ~T2(){}; // should I write my own function here?
};

class Node{
public:
    int data;
    Node* next;
};

class T3{
private:
    int size;
    Node* head;
public:
    T3(size){
        head = new Node[size];
    }
    ~T3(){}; // should I write my own function here?
};

上面的程序中有三個注釋可用來澄清我的問題。 我希望您能向他們解釋,如果能給我一個一般性的規則,我將不勝感激。

對於class T3您正在分配新的內存,因此您將必須刪除處於分解狀態的已分配內存段。

class T3{
private:
    int size;
    Node* head;
public:
    T3(size){
        head = new Node[size];
    }
    ~T3(){
         delete[] head;
      }; 
};

類的析構函數應執行刪除對象時所需的所有操作。

例如,它需要釋放該類動態分配的所有內存。

當您的類是基類,並且希望進行多態銷毀,並且希望銷毀對象時運行某些邏輯時,應該編寫一個析構函數。

如果對象擁有並管理資源 ,則可能需要一個構造函數。 不要忘記復制和賦值運算符。

該對象應自行清除。

IE,如果曾經在對象中分配內存(可能是在構造函數中完成),則應該在析構函數中分配該內存。

析構函數用於清理對象之后。 因此,您也可以做任何事情來幫助您做到這一點。

T1類不需要顯式定義析構函數。 由編譯器隱式定義析構函數就足夠了。

T2類需要顯式定義析構函數,以解除其具有類型指針的數據成員的分配。 否則會發生內存泄漏。

類節點不需要顯式定義析構函數。 T3類必須刪除Node類的所有指針,因為它控制着節點的分配和釋放。

您需要聲明一個析構函數:

  • 如果該類管理的資源在銷毀時需要手動釋放;
  • 如果要用作多態基類,則在這種情況下,它需要一個虛擬析構函數來允許多態刪除。

在第一種情況下,您還需要提供或刪除副本構造函數和副本分配運算符; 否則,您最終可能會遇到兩個或多個嘗試管理同一資源的對象。 這被稱為“三個規則” 通常,您可以使用容器和智能指針等現成的類為您管理內存。 因此通常不需要自己去破壞者。 有人將此稱為“零規則”。

在第二種情況下,析構函數無需執行任何操作(假設該類沒有嘗試管理任何資源),它只需要是虛擬的即可。

對於您的特定示例:

  • T1不需要析構函數
  • T2可能取決於它是否應該管理指針所指向的內容。 如果是這樣,則考慮使用智能指針(如std::unique_ptr<T1>替換指針。
  • T3可能會這樣做,因為它似乎正在管理動態陣列。 您還需要考慮“三法則”。 或考慮使用std::vector<Node>自動管理陣列。

我將嘗試以一種不特定於您的代碼段的一般方式進行回答。

通常會出現兩種一般情況,其中您將需要一個非平凡的析構函數。 這不是一個完整的列表; 只是最常見的情況。

1) 在(多態)層次結構中。 如果您的類是要從中派生的基類,則您的基類很有可能應該具有非平凡的析構函數。 而且,該析構函數可能應該是virtual 這樣就可以通過基類指針刪除派生類對象,如下所示:

class Foo
{
public:
  virtual ~Foo(){}
};

class Bar : public Foo
{
};

int main()
{
  Foo* obj = new Bar;
  delete obj;
}

如果沒有virtual析構函數,此程序將顯示“未定義行為”。

2) 當您的班級中的成員需要的不僅僅是瑣碎的破壞。 一個簡單的示例是,如果您的類的成員是使用new創建的原始指針(不是智能指針)。 該指針將需要delete d,而析構函數可能是正確的選擇。 如果您的類具有復制構造函數或復制賦值運算符( operator= ),則可以很好地表明您的類管理不可分解的成員。 如果您的類中有一個,則可能需要它們一個析構函數來處理分配的所有內容。 (請參閱“三法則” ),但這並不是唯一的指示-您可能只有默認的構造函數,但仍然需要析構函數。 這取決於您的班級。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM