我正在阅读Scott Meyerses C++
,现在我在析构函数中抛出异常部分。以下是他所说的:
当向量
v
被销毁时,它负责销毁所有 它包含的Widget
。假设v
中有Widget
个,其中有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); }
s 仍然需要销毁(否则他们持有的任何资源 会被泄露,所以v应该调用他们的析构函数。 但假设 在这些调用期间,第二个Widget析构函数抛出 例外。现在有两个同时有效的例外
所以,就我理解它而言,如果向量的第一个元素抛出异常,它并不意味着程序在此之后立即被终止。实现尝试破坏向量中的其他对象。让我举个例子:
@if(deniedUsersListCnt > 0){
<script>
$(document).ready(function () {
fancyBoxAjaxGet("/UsersAdmin/_ShowListOfDeniedUsers");
});
</script>
}
function fancyboxAjaxGet(dUrl){
$.fancybox.open({
href: dUrl,
type: "ajax",
ajax: {
type: "GET"
}
});
}
该程序在第一次抛出异常后立即终止。答应在哪里投掷第二个例外?
答案 0 :(得分:3)
如果标准库组件调用的析构函数通过异常退出,则行为未定义。 [res.on.functions] / p2,强调我的:
特别是,在以下情况下效果未定义:
- [...]
- 如果有任何替换函数或处理函数或析构函数通过异常退出,除非特别允许 适用必需行为:段落。
- [...]
答案 1 :(得分:1)
您指的是第8项和第34条;防止例外情况离开析构函数&#34;。你对文本的引用会在句子中截断它:
现在有两个同时有效的异常,,这对于C ++来说太多了。根据出现此类同时活动异常对的精确条件,程序执行会终止或产生未定义的行为。
你表示你已经理解了它,如果向量的第一个元素抛出异常,它并不意味着程序在此之后立即被终止&#34;
嗯,如果你没有抓住它,那就好了,因为那是未被捕获的例外。
或者,你抓住它。通过这样做,你已经离开了正在进行破坏的执行框架,所以 正在进行的任何事情都不再继续。
// 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.
}
}
没有机制可以恢复&#34; f()
的终止代码,发生异常,代码路径已完成,因此如果a
被破坏,b
将永远不会破坏;反之亦然。
好的,你在谈论一个向量。所以你认为std :: vector :: clear正在做类似的事情:
clear() {
while (!empty()) {
try {
erase(back());
} catch (std::exception& e) {
// something went wrong, lets ignore it
}
m_size--;
}
}
您理解&#34;如果发生异常,实现会尝试销毁向量中的其他对象而不是#34;是假的。正如Meyers所说,STL并不期望或鼓励析构函数的例外,因此它并没有尝试处理它们。我不知道你从哪里得到了这种理解,但这是不准确的,抱歉,如果语言试图来实现它,我们就会陷入困境因为如果在尝试销毁某个对象时出现错误而产生异常,那么事情就会变得非常混乱。