考虑以下代码:
std::exception_ptr eptr{ std::current_exception() };
const char* msg = 0;
try {
if (eptr != std::exception_ptr{}) {
std::rethrow_exception(eptr);
}
} catch(const std::exception& ex) {
msg = ex.what();
}
我可以在
msg
之外使用catch
吗?换句话说,ex
是否引用与eptr
相同的异常实例?谢谢! 最佳答案
TL; DR :我不会,因为ex
和eptr
(可能吗?)引用了不同的异常。 (请参阅编辑:可以保证,但是标准不够清晰,以至于我避免依赖它)
异常的生存期由§15.1[except.throw] 统治,具体来说:
但是,您还需要考虑上一段:
因此,在您的情况下会发生什么:
eptr
初始化为指向飞行中的当前异常,从而保证该异常的生存时间至少与ex
初始化为引用,此拷贝是eptr
指向的异常的拷贝msg
指向拷贝,因此悬而未决...除非拷贝和原件在后台都共享相同的消息。 确保异常的生命周期足以满足您的目的的唯一方法是直接创建
std::exception_ptr
。编辑拉尔夫·坦德斯基(Ralph Tandetzky)大胆地注意到§18.8.5[propagation] 说:
这表明在以下段落中:
Throws子句不应解释为某种
throw *p;
,而应具有与throw;
相同的行为(重新抛出完全相同的实例,而不是拷贝)。但是,由于在第7款中有一个if,看来它也可能是拷贝...注意:有趣的实验表明the underlying object may be shared ...与我对标准的阅读相矛盾;我不太理解复制初始化如何被不同地解释。