一个物体可以抛出吗?

时间:2014-03-07 21:59:55

标签: c++ exception

回答最近关于例外的问题,让我想起了一个旧查询。

以下在c ++中编译

#include <iostream>
using namespace std;

struct weird {
    void danger()
    {
        throw *this;
    }
};

int main() 
{
    weird object;
    object.danger();
    return 0;
}

但它总是会导致运行时错误。

  • 在堆栈展开期间是不是抛出了对象?

  • 运行时错误闻起来像是对terminate的调用,这是怎么回事?

  • 如果在封闭范围内宣布weird object(全局在这里),这可以在内部范围内工作吗? (展开那个堆栈不会影响优质堆栈?)

2 个答案:

答案 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派生出来。