为什么在异常处理c ++中捕获之前需要try块

时间:2016-10-01 13:55:51

标签: c++ exception-handling

是否可以抛出异常并在不使用try块的情况下捕获它? 例如:

int main()
{
    throw 1;
    catch(int){
       std::cerr << "caught exception\n";
    }
    return 0;
}

2 个答案:

答案 0 :(得分:0)

根据我的经验,你必须在组合中使用try和catch块。这里如果try块中发生任何错误,那么只将它传递给catch块。因此,如果没有try块,那么它将不知道在哪里寻找错误。因此,它们需要组合使用。我不确定在C ++中,但在Java中,如果将类扩展为throwable,则可以单独使用catch块。

答案 1 :(得分:-2)

在飞行中的异常期间,程序控制流程的行为略有不同。 try-catch阻止希望将程序恢复到通常的控制流程。

当程序中的任何一点抛出异常时。 正常程序控制流停止。程序控制流现在通过运行时的异常处理机制。这与 normal 不同。对于普通,自动存储的析构函数始终在控制流到达范围(生命周期) }的末尾时运行。对于飞行中的例外,它们早于正常运行

考虑一下(注意评论);

MyClass foo(){
{
    MyClass c;
    c.call(balhhh); //assuming this throws

    // (1)

    ....
    return c;
 }

void bar(){
     std::map<K,V> mp;
     auto c = foo();

     // (2)

     mp.insert(c);
     ....
}

当您致电bar时,我们可以看到控制流是如何在foo()处完全离开// (1),在// (1)之后的任何其他代码都不会在foo()范围内执行foo(),当// (2)被解除时,同样的事情就发生了,我们现在在main()

这在整个堆栈展开过程中都会发生,并且这会递归展开所有函数......直到我们回到调用std::terminate的{​​{1}}。

现在,使用 try-catch 块,编译器生成的代码在程序移动到catch块后暂停早期退出行为(搜索匹配)处理程序),如果处理异常,控制流程将恢复正常。

考虑:

MyClass foo() 
    try {
        MyClass c;
        c.call(balhhh); //assuming this throws

        // (1)

        ....
        return c;
     }
     catch(...){
          ...
     }

void bar(){
     std::map<K,V> mp;
     auto c = foo();

     // (2)

     mp.insert(c);
     ....
}

现在,当异常离开时,控制流离开// (1)的范数以搜索关联的catch中的处理程序,如果处理了异常,程序将返回正常的控制流程。 // (2)之后的代码现在将执行...

从解释中可以看出, try-catch 块是C ++标准规定的唯一方法,用于在抛出异常后恢复正常程序控制流

int main()
{
    throw 1;   //fine, program control leaves the whole of main at this point.
    catch(int){    //illegal, like using an else block without an if
       std::cerr << "caught exception\n";
    }
    return 0;
}

即使上述代码合法,throw表示控件会将整个封闭范围留在throw网站。