16

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

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

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

解释是什么?我以为这throw;只是throw ExceptionJustCaught;.

4

2 回答 2

16

异常对象有点特殊。它们是在内存中的一个特殊位置构建的,它们的生命周期由它们被捕获的 catch 块决定。

如果您说throw e;,原始异常的生命周期在 catch 块的末尾结束,并且您通过复制抛出一个新异常e,从而产生一个经典的切片问题:Sincee是对动态类型通常更多的对象的多态引用-derived than std::exception,你最终会切掉对象的派生部分。

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

于 2012-09-22T23:08:59.063 回答
9

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

于 2012-09-22T22:02:02.333 回答