考虑以下代码:

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 :我不会,因为exeptr(可能吗?)引用了不同的异常。 (请参阅编辑:可以保证,但是标准不够清晰,以至于我避免依赖它)

异常的生存期由§15.1[except.throw] 统治,具体来说:



但是,您还需要考虑上一段:



因此,在您的情况下会发生什么:

  • eptr初始化为指向飞行中的当前异常,从而保证该异常的生存时间至少与
  • 一样长
  • ex初始化为引用,此拷贝是eptr指向的异常的拷贝
  • 当catch子句结束时,拷贝死于
  • msg指向拷贝,因此悬而未决...除非拷贝和原件在后台都共享相同的消息。

  • 确保异常的生命周期足以满足您的目的的唯一方法是直接创建std::exception_ptr

    编辑拉尔夫·坦德斯基(Ralph Tandetzky)大胆地注意到§18.8.5[propagation] 说:



    这表明在以下段落中:



    Throws子句不应解释为某种throw *p;,而应具有与throw;相同的行为(重新抛出完全相同的实例,而不是拷贝)。但是,由于在第7款中有一个if,看来它也可能是拷贝...

    注意:有趣的实验表明the underlying object may be shared ...与我对标准的阅读相矛盾;我不太理解复制初始化如何被不同地解释。

    08-17 15:08