作者热门文章
- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我知道 C++ 中的当前规则是这样说的:
if a destructor throws while already stack unwinding because of a exception then
std::terminate
is called.
在探索为什么规则是这样的时候,我遇到了下面代码中描述的情况。
X
的析构函数抛出。
Y
在它自己的析构函数中删除一个 X
。
因此 Y
的析构函数抛出。
我不清楚 Y
抛出 (3.) 是否应该按照标准规则触发 std::terminate
。我希望它不会,并且针对 gcc
的测试如我希望的那样运行。
熟悉标准法律术语的人可以澄清一下吗? (3.) 是否应该触发 std::terminate
?
#include <iostream>
struct X {
~X() noexcept(false) {
std::cout << "Destroying X\n";
throw std::runtime_error("Exception");
}
};
struct Y {
X * x_;
explicit Y(X * x) : x_{x} { }
~Y() noexcept(false) {
std::cout << "Destroying Y\n";
delete x_;
}
};
int main() {
try {
Y y(new X());
std::cout << "Living\n";
}
catch (const std::exception & e) {
std::cout << "Caught " << e.what() << '\n';
}
}
使用 g++ 版本 5.4.0-6ubuntu1~16.04.9 和 --std=c++17
我得到:
Living
Destroying Y
Destroying X
Caught Exception
最佳答案
标准在[except.terminate]p1.4中说:
- when the destruction of an object during stack unwinding terminates by throwing an exception, or
2) 发生是因为 y
超出范围。 1) 抛出异常,开始堆栈展开。在堆栈展开期间,更具体地说是在销毁 Y
时 - 即 2)。它抛出一个异常,因此满足该点并调用 std::terminate
。
这正是您的代码正在做的事情,除了重要的一点:在堆栈展开期间。堆栈展开不会在范围结束时发生,它只会在抛出异常并超出抛出的当前范围时发生。
Y
没有因为异常而被销毁。添加 throw 1;
以查看对 std::terminate
的调用。
因此,该条款不适用,您的代码确实有效。
关于c++ - 删除从析构函数调用的抛出析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49290248/
我是一名优秀的程序员,十分优秀!