PAYATHON 2026

C++ 协程的 unhandled_exception() 中能否使用 throw;?

数据阿明

结论

可以。C++ 协程因异常退出时,协程机制会捕获异常并调用 promise 对象的 unhandled_exception()。调用发生在处理该异常的异常处理器中,因此函数里的 throw; 会重新抛出当前异常,并由后面的 catch 分支接住。

问题中的关键结构是:

try {
    throw;
} catch (const std::exception& e) {
    // 处理 std::exception
} catch (...) {
    // 处理其他异常
}

为什么有效

单独使用 throw; 时,它会重新抛出当前正在处理的异常。协程运行时调用 unhandled_exception() 时,协程体抛出的异常仍在处理中,因此这里可以重新抛出。函数中的 catch 分支会接住该异常。

这种写法可以用于原代码中的异常分类处理。它与先通过 std::current_exception() 获取当前异常,再用 std::rethrow_exception() 重新抛出的做法相符。

适用条件

这个结论适用于协程异常处理流程调用 unhandled_exception() 的情况。如果没有正在处理的异常时直接调用该函数,throw; 没有可重新抛出的异常,会调用 std::terminate()。因此,不应把这种调用方式当作普通函数调用。

原代码将 unhandled_exception() 声明为 noexcept,并在两个分支中显式调用 std::terminate()。如果日志输出本身抛出异常,程序也会因函数是 noexcept 而终止。使用 std::println 时,还需确认编译环境支持它,并包含相应头文件。这些条件不影响 throw; 在协程异常处理器中的语义。

备注:内容仅供参考。