今天我在catch
区块中发现了一个错误:
catch (const exception& e){
// do something
// throw e; <-- bug!
throw; // <-- right thing to do
}
基本上,如果我明确地重新提出异常e
,我会重新构建一个新的std::exception
,实际上来自what()
方法的消息是默认的{{ {1}},而不是我自定义构建的消息。
解释是什么?我认为std::string
只是throw;
的缩写。
答案 0 :(得分:14)
异常对象有点特殊。它们是在记忆中的特殊位置构建的,它们的生命周期取决于它们被捕获的捕获区。
如果你说throw e;
,原始异常的生命周期在catch块结束时结束,你通过复制e
抛出一个新的异常,从而产生一个经典的切片问题:由于e
是对动态类型通常比std::exception
更多派生的对象的多态引用,因此最终会切除对象的派生部分。
相比之下,throw;
是一个特殊的语句,它重新激活原始异常,因此它不再被捕获,并且它的生命周期 not 不再在块的末尾结束。实际上,如果您通过非常量引用捕获,则可以继续修改异常对象并重新抛出,从而将状态更改传递到较低的catch块。但请记住,重新抛出与抛出新的异常不同!
答案 1 :(得分:8)
只有throw
通过引用抛出当前异常。 throw e
copy构造一个新的异常抛出。这与return
的工作方式大致相同。