簡體   English   中英

刪除從析構函數調用的引發析構函數

[英]Delete throwing destructor called from destructor

我了解C ++中的當前規則表明:

如果析構函數由於異常而在已經展開堆棧時拋出了異常,則調用std::terminate

在探究規則為何如此時,我遇到了以下代碼中描述的情況。

  1. X的析構函數拋出。

  2. Y刪除其自己的析構函數中的X

  3. 因此, Y的析構函數拋出。

我不清楚Y拋出(3.)的事實是否應該觸發標准規則的std::terminate 我希望它不應該如此,並且針對gcc測試按我希望的那樣運行。

熟悉標准法律法規的人可以澄清這一點嗎? (3.)是否應該觸發std::terminate

#include <iostream>

struct X {
  ~X() noexcept(false) {
    std::cout << "Destroying X\n";
    throw std::runtime_error("Exception");
  }
};

struct Y {
   X * x_;

  explicit Y(X * x) : x_{x} { }

  ~Y() noexcept(false) {
    std::cout << "Destroying Y\n";
    delete x_;
  }
};

int main() {
  try {
    Y y(new X());
    std::cout << "Living\n";
  }
  catch (const std::exception & e) {
    std::cout << "Caught " << e.what() << '\n';
  }
}

使用帶有--std=c++17 g ++版本5.4.0-6ubuntu1〜16.04.9,我得到:

Living
Destroying Y
Destroying X
Caught Exception

該標准在[except.terminate] p1.4中說

  • 當堆棧展開期間對象的銷毀因引發異常而終止時,或者

2)發生是因為y超出范圍。 1)引發異常,這開始堆棧展開。 在堆棧展開期間,更具體地說,在破壞Y同時-2)。 它拋出一個異常,因此滿足了這一點,並調用了std::terminate

除了要注意的一點: 堆棧展開期間 ,這正是您正在執行的代碼。 范圍結束時不會發生堆棧展開,僅當引發異常並超出引發它的當前范圍時才會發生堆棧展開。

Y沒有因為異常而被破壞。 throw 1; 查看對std::terminate的調用。

因此,該子句不適用,您的代碼確實有效。

暫無
暫無

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

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