引发异常的析构函数
Destructor throwing an exception
我正在阅读Scott Meyerses C++
,现在我在析构函数抛出异常部分。他是这么说的:
因此,据当载体
v
被销毁时,它负责销毁所有 它包含的Widget
。假设v
有十个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 不期望或鼓励析构函数的异常,因此它不会尝试处理它们。我不知道你从哪里得到这种理解,但它是不准确的,对不起,如果语言试图实现它,我们将陷入真正的混乱,因为如果出现问题到足以在尝试破坏对象时生成异常,事情会变得非常混乱。
- 在析构函数内部处理异常(但不抛出)
- 在 postOrderDelete 上调用析构函数时引发的异常
- 为什么在析构函数中引发异常时不调用重载删除
- 文件流析构函数是否可以在C++中引发异常?
- 为什么没有捕获我来自析构函数的异常
- 析构函数中的互斥锁C++在 Python 中调用 exit() 时会导致异常
- 旧代码在析构函数中引发异常
- 引发导致调用析构函数的异常会使程序崩溃
- 为什么我的析构函数中的异常没有触发 std::终止?
- 如何释放C++异常类析构函数中的变量
- 析构函数中的 C++ 异常
- 在scoped_ptr发生异常的情况下未调用析构函数
- 在由于异常而展开时处理C++析构函数中的pthread取消点
- c++中的Guard,在main中未处理异常时不调用析构函数
- 如何为析构函数指定nothrow异常说明符
- 堆栈异常处理和析构函数展开.如何使用这些信息
- 析构函数的异常调用
- 重写std的析构函数:异常
- c++ RAII析构函数异常
- C++析构函数异常