回答最近关于例外的问题,让我想起了一个旧查询。
以下在c ++中编译
#include <iostream>
using namespace std;
struct weird {
void danger()
{
throw *this;
}
};
int main()
{
weird object;
object.danger();
return 0;
}
但它总是会导致运行时错误。
在堆栈展开期间是不是抛出了对象?
运行时错误闻起来像是对terminate
的调用,这是怎么回事?
如果在封闭范围内宣布weird object
(全局在这里),这可以在内部范围内工作吗? (展开那个堆栈不会影响优质堆栈?)
答案 0 :(得分:12)
结果是调用std::terminate()
,因为异常永远不会被捕获。将其更改为以下内容并且工作正常:
int main() {
weird object;
try {
object.danger();
}
catch (weird &w) {
std::cout << "caught weird\n";
}
}
- 在堆栈展开期间是不是抛出了对象?
当抛出异常时,异常抛出机制会将抛出的值的副本复制到某个私有内存中,因此“抛出”对象的生命周期并不重要。
(当然如果你抛出一个指针,那么指针值就会被保留,而不是指向对象。在这种情况下,你必须确保catch处理程序不会通过指针值做非法操作,或者通过确保对象仍然存在,或者catch处理程序不遵循指针。)
- 运行时错误闻起来像是对
terminate
的调用,这是怎么造成的?
当抛出异常并且没有相应的catch处理程序时,C ++声明必须调用std::terminate()
。负责查找适当的catch处理程序的异常抛出机制通过在找不到合适的catch处理程序时调用std::terminate()
来实现这一点。
- 如果在封闭范围内宣布
weird object
(全局在这里),这可以在内部范围内工作吗?
它是否全球无关紧要;抛出异常的行为(大部分)都是明确定义的。
(实现指定的一件事是,如果在没有找到catch处理程序的情况下调用std::terminate()
之前堆栈被解开。我相信在大多数实现中,堆栈在这种情况下不会解开。)
答案 1 :(得分:0)
当它转到C ++中的异常时,请记住: 按值投掷,按引用引用 。
“按值”=复制,复制=您不再需要关心原始对象会发生什么。
旁注:如果您要使用throw
个自己的类型,最好从std::exception
派生出来。