从catch块重新抛出异常时丢失异常类型

时间:2012-09-22 21:58:26

标签: c++ exception try-catch

今天我在catch区块中发现了一个错误:

catch (const exception& e){
    // do something
    // throw e; <-- bug!
    throw;    // <-- right thing to do
}

基本上,如果我明确地重新提出异常e ,我会重新构建一个新的std::exception,实际上来自what()方法的消息是默认的{{ {1}},而不是我自定义构建的消息。

解释是什么?我认为std::string只是throw;的缩写。

2 个答案:

答案 0 :(得分:14)

异常对象有点特殊。它们是在记忆中的特殊位置构建的,它们的生命周期取决于它们被捕获的捕获区。

如果你说throw e;,原始异常的生命周期在catch块结束时结束,你通过复制e抛出一个新的异常,从而产生一个经典的切片问题:由于e是对动态类型通常比std::exception更多派生的对象的多态引用,因此最终会切除对象的派生部分。

相比之下,throw;是一个特殊的语句,它重新激活原始异常,因此它不再被捕获,并且它的生命周期 not 不再在块的末尾结束。实际上,如果您通过非常量引用捕获,则可以继续修改异常对象并重新抛出,从而将状态更改传递到较低的catch块。但请记住,重新抛出与抛出新的异常不同!

答案 1 :(得分:8)

只有throw通过引用抛出当前异常。 throw e copy构造一个新的异常抛出。这与return的工作方式大致相同。