为什么不能从析构函数抛出异常,但可以从复制构造函数抛出异常
Why cannot throw exceptions from destructors but can from copy constructor?
似乎在析构函数抛出多个异常的情况下,你不能从析构函数抛出异常。
在Effective c++中,Scott Meyers使用了一个vector示例,其中第一个元素在析构期间抛出异常,然后第二个元素抛出,这对c++造成了问题(c++不能处理多个异常)。
当然这种情况(向量操纵元素和元素抛出异常)也可能发生在复制构造函数实现深度复制期间?
编辑:我们是在说,调用底层函数的递归性质与复制构造函数不同吗?
异常不应该从析构函数中抛出,因为当抛出异常时,编译器将清除作用域中的变量,从而调用它们的析构函数。如果这些也抛出异常,您将处于糟糕的状态。
构造函数和析构函数的不同之处在于
-
首先,对象的销毁与unwind绑定在一起,而unwind在抛出异常时发生。展开与对象的构造无关。也就是说,析构函数和异常之间已经存在一种关系。
-
当某些代码在对象的构造过程中被中断时,可以安全地处理。可以回滚资源,就好像从未请求过对象的创建一样。此外,后续代码不运行也没关系,比如其他对象的构造。在销毁的情况下,必须正确执行,否则资源会泄漏。放弃析构函数是不对的,因为这是清理对象的最后机会。此外,如果析构函数是多个调用链的一部分,则永远不调用其余析构函数是不行的。忽略执行析构函数会导致程序出现一些永久性的问题。
假设你有这样的情况:
{
A a;
B b;
C c;
// ...
}
假设块中的语句抛出,则A、B和C的析构函数按相反的顺序执行:C::~C
、~B::B
和A::~A
。假设C::~C
抛出。这意味着不仅c
的破坏是不完整的,而且B
和A
的破坏也不会发生。该语句块的清理代码将被丢弃。
语义应该是什么?
如果在这种情况下没有析构函数可以被放弃,这意味着C::~C
必须在抛出时重新执行。但这可能会触发一个无限循环。
或者,unwind仍然可以执行b
和a
的剩余析构函数。但这仍然意味着C
的析构函数被抛弃了,C
没有被正确地销毁。
- 从构造函数抛出异常时如何克服内存泄漏
- 函数如何通知用户它基于函数原型抛出异常?
- 在缺少函数重载时抛出异常,并带有 std::variant 而不是编译时错误
- VisualStudios 会抛出异常,而代码块不会 [C++]
- 如果不包含 pthread,为什么 GCC 的线程标准库实现会抛出异常?
- ZMQ::send() 抛出异常并终止 QNX 进程.为什么以及如何从中恢复?
- new(std::nothrow) int[n] 抛出异常
- 为什么g_object_set抛出异常(vcruntime140.dll)?
- 你能防止 std::regex 在无效表达式上抛出异常吗?
- C++子线程抛出异常
- 我们应该在抛出异常之前取消分配内存吗
- 有没有一种方法可以让OpenCLC++绑定为所有错误抛出异常
- 为什么访问模板化变体作为返回值抛出异常
- 如何实现,错误分配中止而不是抛出异常
- std::p riority_queue::p op什么时候会抛出异常
- 在0x5914F3BE抛出异常(基于.dll)
- std::vector 默认构造函数可以抛出异常吗?
- 挂钩创建文件抛出异常:读取访问冲突
- getaddrinfo 抛出异常
- 为什么不能从析构函数抛出异常,但可以从复制构造函数抛出异常