co_return是协程专用返回语句,需配合promise_type使用,触发return_void()/return_value()并进入final_suspend状态,而非直接返回调用方。

co_return 是协程的返回语句,不是普通函数 return 的替代品
它只在标记为 coroutine 的函数(即含 co_await、co_yield 或 co_return 的函数)中合法,且必须配合自定义的协程桩(promise_type)才能工作。编译器看到 co_return 会生成对 promise.return_void() 或 promise.return_value(...) 的调用,而不是直接结束函数。
常见错误现象:error: 'co_return' cannot be used in a function that is not a coroutine——说明函数没被识别为协程,通常因为没用到其他协程关键字,或编译器未启用 C++20 协程支持(如没加 -std=c++20 和 -fcoroutines)。
- 使用场景:异步 I/O 完成后返回结果(如
Task<int></int>)、生成器末尾收尾(Generator<void></void>)、资源清理后退出协程 - 若协程返回类型是
void(如Task<void></void>),必须调用promise.return_void();若返回非 void(如int),则调用promise.return_value(val) - 不写
co_return也不报错,但协程会在函数末尾隐式调用return_void();显式写更清晰,尤其需要提前退出时
co_return 后协程不立即销毁,而是进入 final_suspend 状态
这是最容易被忽略的一环:co_return 执行完,协程帧(coroutine frame)不会自动释放,而是先挂起在 promise.final_suspend() 返回的 awaiter 上。是否继续执行、何时销毁,全由这个 awaiter 决定。
典型陷阱:忘了重载 final_suspend,或返回了 std::suspend_always{} 却没手动 destroy(),导致协程泄漏、内存不释放。
立即学习“C++免费学习笔记(深入)”;
- 如果希望协程结束后立刻销毁(最常见需求),
final_suspend()应返回std::suspend_never{} - 如果要移交控制权(比如把协程句柄交给 event loop 处理),可返回
std::suspend_always{},并在外部调用handle.destroy() - 返回
std::suspend_always{}时,handle.done()会返回true,但handle.destroy()必须由用户显式调用,否则协程帧永远驻留
co_return 表达式的类型必须能被 promise_type 接受
co_return expr; 中的 expr 类型,必须和 promise_type::return_value(T&&) 的参数类型匹配(或能隐式转换)。否则编译失败,错误信息往往指向 promise 类型里缺失该函数。
例如:声明 Task<:string></:string> 却在协程里写 co_return 42;,就会触发类似 no matching member function for call to 'return_value' 的错误。
- 基本类型(
int、std::string)通常走return_value(T&&) - void 协程只能用
co_return;(无表达式),触发return_void() - 如果想支持多种返回方式(如允许
co_return和co_return std::move(x)),需同时提供return_value(const T&)和return_value(T&&) - 注意移动语义:
co_return local_obj;默认触发移动(如果T可移动),但若return_value参数是const T&,就只能拷贝
别把 co_return 当 return 用——它不传递值给调用方
co_return 的值不是“返回给调用者”,而是传给协程的 promise,再由 promise 决定如何暴露(比如存入 Task 对象内部、触发回调、填充 future)。调用协程函数得到的只是句柄(std::coroutine_handle)或包装对象(如 Task<int></int>),真正取结果得靠后续机制(如 co_await 或 get())。
新手常误以为 auto x = my_coro(); co_return 123; 会让 x 直接等于 123,其实 x 是个待调度的协程对象,里面还没运行,更没结果。
- 同步获取结果?不行——协程默认惰性求值,必须驱动它(如
co_await x或x.get(),后者通常阻塞等待) - 想让
co_return val最终变成调用方拿到的val,必须确保 promise 正确存储val,且 awaiter 的await_resume()返回它 - 性能影响:每次
co_return都涉及一次promise.return_value()调用 + 可能的移动/拷贝;避免在热路径频繁返回大对象
final_suspend 或写错 return_value 签名,编译期可能不报错,但运行时行为完全不可控。









