You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不使用std::current_exception为std::promise设置异常的可行方案

C++ promise直接设置指定异常的实现方案

完全可以直接给set_exception传入指定异常,根本不需要走「先抛出再捕获拿std::current_exception」的繁琐流程——其实你贴的参考示例的注释里已经给出了方案,就是用标准库自带的std::make_exception_ptr生成异常指针传入即可,你担心的生命周期问题、内存泄漏问题在标准用法下都不存在。

核心原理

std::exception_ptr本身带引用计数托管能力,只要是通过标准库合规接口生成的exception_ptr,会自动管理持有的异常对象生命周期:最后一个指向该异常的exception_ptr销毁时,异常对象会自动被回收,既不会因为局部对象出作用域销毁出现悬垂指针,也不会有手动分配内存导致的泄漏。
你担心的问题只会出现在手动new异常、拿局部异常裸指针强转这类错误用法里,走标准接口完全没这个问题。

简化后的代码实现

原示例里两层try-catch的冗余逻辑可以大幅精简,不需要为了拿异常指针主动触发异常抛出:

std::thread t([&p]{
    try {
        // 直接构造异常并生成exception_ptr传入,无需throw-catch流程
        p.set_exception(std::make_exception_ptr(std::runtime_error("Example")));
        // 自定义异常用法完全一致
        // p.set_exception(std::make_exception_ptr(MyException("mine")));
    } catch(...) {
        // 这里仅需要捕获set_exception本身可能抛出的异常
        // 比如promise已经设置过值/异常时会抛出std::future_error
    }
});

注意事项

  • std::make_exception_ptr会自动把传入的异常对象拷贝/移动(支持移动语义的类型会优先移动,开销很低)到自己管控的内存空间,和原局部对象的生命周期完全解绑,不会出现悬垂问题。
  • 这种写法比throw再捕获的流程性能更好,省掉了异常抛出、栈展开的额外开销,C++11及之后的标准版本都原生支持,可放心使用。
  • 不要尝试手动new异常对象、取局部异常变量的地址强转为exception_ptr,这类非标准用法才会触发你担心的生命周期、内存泄漏问题。

内容的提问来源于stack exchange,提问作者Lorah Attkins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 03:03:29