簡體   English   中英

如何正確實現 C++ class 析構函數

[英]How to properly implement a C++ class destructor

在 class (沒有直接指針成員)中,我看到定義析構函數有以下 3 種可能性。

class Child : public Parent
{
public:
    // ~Child() override {}          // (1) explicit destructor with empty body
    // ~Child() override = default;  // (2) explicit default destructor
    //                               // (3) implicit default destructor


private:
    // members
}

可以/應該始終避免選項(1)嗎? 因為如果我使用選項(1) ,Clang-Tidy 會提示我選擇選項(2) )。

一般來說,這三種不同的選項之間有什么區別? 選擇其中之一時應考慮什么?

可以/應該始終避免選項(1)嗎?

假設語言的非古代版本,是的。 據我所知,使用空的非默認析構函數的唯一原因是支持 C++03 和舊標准。

選擇其中之一時應考慮什么?

    1. 和 3. 具有在 C++ 的所有版本中都有效的優點(忽略override說明符)。
    1. 3. 只要成員可以簡單地破壞,就具有微不足道的優勢。
    1. 和 2. 具有允許將析構函數與 class 定義分開定義的優點(在示例中沒有利用)。 例如,如果您有一個指向不完整類型的唯一指針作為成員,這一點至關重要。 這在實現 PIMPL 模式時很典型。
    1. 和 2. 還具有允許析構函數顯式聲明為虛擬的優點,這通常是多態基類所必需的。
    1. 不推薦使用隱式聲明的復制構造函數和賦值運算符的缺點。 這意味着不應該依賴它,並且將來可能會停止工作。 1. 和 2. 都具有阻止隱式移動構造函數和賦值運算符生成的缺點。 因此,如果您使用其中任何一個,那么您還應該聲明復制和移動構造函數和賦值運算符(如果可能,作為默認值)。
    1. 具有寫作量最少,閱讀量最少的優點,尤其是考慮到上一段。

作為一個粗略的經驗法則,如果可能,請使用 3.。 如果不可能(例如,上面描述的 PIMPL 案例),則使用 2。如果不可能(即您需要支持 C++03),則使用 1。

可以/應該始終避免選項(1)嗎?

如果你沒有任何東西可以放入析構函數,那么你應該讓編譯器為你生成一個default的析構函數,所以是的。

一般來說,這三種不同的選項之間有什么區別?

假設沒有什么特別的東西需要放入你的析構函數中:

  1. 您將析構函數鎖定為空,如果發生變化,您可能會忘記將它們添加到析構函數中。

  2. 讓編譯器弄清楚這一切,並在代碼中顯示你這樣做。

  3. 讓編譯器把它弄清楚,不要在代碼中顯示你這樣做。

C++采用RAII原理。 密切相關的是三/五/零規則

它是這樣的:

  • 如果您的 class 是資源的所有者,那么它必須實現所有 3/5 特殊成員(復制/移動構造函數、復制/移動賦值和析構函數)以遵守 RAII 原則
  • 根據如果您需要定義至少一個 3/5 特殊成員,那么您的 class 很可能擁有一個資源,因此您必須定義所有 3/5
  • 如果您的 class 擁有資源,則它必須專門處理該資源的預訂。 否則它不應該定義任何提到的特殊成員(零規則)。

您絕對屬於零規則領域,您的所有代碼也應該如此。 所以你需要有隱式析構函數。

暫無
暫無

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

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