簡體   English   中英

析構函數引發異常

[英]Destructor throwing an exception

我正在閱讀Scott Meyerses C++ ,現在在析構函數的拋出異常部分。 他說的是這句話:

當向量v被銷毀時,它負責銷毀它包含的所有Widget 假設v有十個Widget ,並且在銷毀第一個Widget拋出異常。 其他九個 Widget 仍然必須銷毀(否則它們擁有的任何資源都 將被泄漏)因此v應該調用其析構函數 但是假設 在這些調用期間,第二個Widget析構函數將引發 異常。 現在有兩個同時活動的異常

因此,據我所知,如果向量的第一個元素引發異常,這並不意味着程序會在此之后立即終止。 該實現嘗試改為破壞向量中的其他對象。 讓我舉一個例子:

#include<iostream>
#include<vector>

struct A
{
    ~A(){ std::cout << "destruction" << std::endl; throw std::exception(); }
};

int main()
{
    A a[] = {A(), A(), A(), A(), A(), A()};
    std::vector<A> v;
    v.assign(a, a+6);
}

DEMO

該程序在第一次拋出異常后立即終止。 所承諾的第二個異常拋出在哪里?

如果由標准庫組件調用的析構函數通過異常退出,則該行為未定義。 [res.on.functions] / p2,重點是:

特別是在以下情況下,效果是不確定的:

  • [...]
  • 如果任何替換函數或處理函數或析構函數操作通過異常退出,除非適用的“ 必需的行為:”段落中特別允許。
  • [...]

您指的是第8項“防止離開析構函數的異常”。 您對文本的引用將句子中間的部分截斷:

現在有兩個同時活動的異常這對於C ++來說太多了 取決於此類同時發生的異常對的精確產生條件,程序執行要么終止,要么產生不確定的行為。

您指出您“沒有理會它,如果向量的第一個元素引發異常,並不意味着程序在此之后立即終止”

好吧,如果您沒有抓住它,它也會這樣做,因為那是未捕獲的異常的作用。

另外,您也可以抓住它。 這樣,您就離開了進行銷毀的執行框架,因此,正在進行的任何事情將不再進行。

// speculative "what if"

struct A { ~A() { raise std::exception(); } };

void f() {
   A a, b;
} // b and a go out of scope, the first one throws

int main() {
    try {
        f();
    } catch (...) {
        // << program is now here.
    }
}

沒有機制可以“恢復” f()的終止代碼,發生了一個異常,即代碼路徑已完成,因此,如果a被破壞, b將永遠不會被破壞。 或相反亦然。

好的,您正在談論向量。 因此,您認為std :: vector :: clear正在執行類似的操作:

clear() {
    while (!empty()) {
        try {
            erase(back());
        } catch (std::exception& e) {
            // something went wrong, lets ignore it
        }
        m_size--;
    }
}

您對“如果發生異常,則實現會嘗試破壞向量中的其他對象”的理解是錯誤的。 正如Meyers所說,STL不會期望或鼓勵析構函數的異常,因此它不會嘗試處理它們。 我不知道您從何處獲得這種理解,但這並不准確,對不起,如果該語言嘗試實現它,我們將陷入一片混亂,因為如果某個錯誤出了錯,足以在破壞銷毀程序時產生異常,對象,事情會變得非常混亂。

暫無
暫無

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

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