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

Promise的final_suspend是否应始终返回std::suspend_always?

关于C++20协程final_suspend的疑问与解析

在Josuttis所著的C++20书籍中,第14.2.5节第476页提到:

  • final_suspend用于定义协程是否应在最终阶段挂起。这里我们指定要执行挂起,这通常是正确的做法。注意该成员函数必须保证不抛出异常,它应始终返回std::suspend_always{}。

这段表述看起来有些矛盾——如果final_suspend确实“应始终返回std::suspend_always{}”,那标准为何不直接简化要求,让它返回void,由编译器自动插入std::suspend_always{}的逻辑?

事实上,该书后续第15.7.3节第536页就给出了反例:final_suspend返回了一个自定义的FinalAwaiter等待器,用于实现对称转移。这个等待器的await_ready和await_resume行为和std::suspend_always一致,但await_suspend逻辑不同,会返回目标协程句柄或空操作协程句柄:

struct FinalAwaiter {
  bool await_ready() noexcept { return false; }
  std::coroutine_handle<> await_suspend(CoroTask::CoroHdl h) noexcept {
    if (h.promise().contHdl) {
      return h.promise().contHdl;
    } else {
      return std::noop_coroutine();
    }
  }
  void await_resume() noexcept {}
};

回到最初的表述,它的“深意”在于针对绝大多数常规场景的简化指导:

  • 对于普通的协程使用场景(比如简单的任务返回、生成器),final_suspend返回std::suspend_always是最安全的选择:它确保协程结束时不会自动销毁自身,而是把销毁的控制权交给持有协程句柄的调用方,避免悬空引用或提前释放资源。
  • 而返回自定义等待器是高级场景的特殊需求,比如对称转移、自定义资源清理逻辑等,这类场景属于“例外情况”,不是初学者或常规使用时需要考虑的。

Josuttis在前期章节先给出最通用、最安全的规则,是为了帮助读者先建立正确的基础认知,后续再逐步引入高级用法,符合循序渐进的教学逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 20:40:22