[英]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);
}
該程序在第一次拋出異常后立即終止。 所承諾的第二個異常拋出在哪里?
如果由標准庫組件調用的析構函數通過異常退出,則該行為未定義。 [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.