co_return在c++20协程中需配合合规promise_type使用,返回值经return_value()存入promise,协程结束后通过显式接口获取;co_return后不可继续执行,否则行为未定义。

co_return 在 C++20 协程中怎么写才不报错
直接用 co_return 返回值本身不报错,但协程函数必须声明为协程(即函数体内含 co_await、co_yield 或 co_return),且其返回类型必须满足协程约定——最常见错误是返回 void 却想取结果,或返回自定义类型但没实现 promise_type。
比如写成这样会编译失败:
auto my_coro() {
co_return 42; // ❌ 错误:返回类型 auto 无法推导协程 promise,且没声明为协程
}
正确做法是明确返回类型,并确保该类型有合规的 promise_type。标准库没提供通用协程返回类型,得自己写或用第三方(如 std::experimental::generator 已废弃,推荐 cppcoro 或手写)。
返回 int / std::string 等值类型时,promise_type 怎么配
协程返回值不是直接“吐出来”,而是通过 promise_type::return_value(T&&) 存入 promise 对象,再由协程句柄(std::coroutine_handle<p></p>)在恢复后读取。所以你不能只关心 co_return x;,还得让 promise_type 支持接收并保存 x。
-
return_value(const T&)和return_value(T&&)都要实现,否则移动语义可能触发编译错误 - 如果返回类型是
std::string,而promise_type里只存std::string*却没管理生命周期,容易悬垂 - 不要在
return_value里抛异常——协程启动失败时可抛,但co_return执行期间抛异常会导致未定义行为(除非 promise 显式处理)
示例片段(简化版):
struct Task {
struct promise_type {
int result_;
auto get_return_object() { return Task{std::coroutine_handle<promise_type>::from_promise(*this)}; }
auto initial_suspend() { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
void return_value(int v) { result_ = v; } // ✅ 接收 int
void unhandled_exception() { std::terminate(); }
};
// ... 构造/析构/await_transform 省略
};</promise_type>
co_return 后还能继续执行吗
不能。co_return 是协程的终点语句,它会触发 promise.final_suspend(),然后协程状态变为 *finished*。之后若再调用 handle.resume(),行为未定义(通常 crash 或静默失败)。
注意几个易混淆点:
-
co_return;(无表达式)适用于返回类型为void的协程,但该协程仍需完整 promise(哪怕return_void()是空实现) -
co_return expr;和co_return (expr);语义相同,括号不改变求值顺序或拷贝行为 - 如果在
co_return后写了代码(哪怕被 if(false) 包裹),GCC/Clang 会警告 “unreachable code”,因为协程帧在co_return后已标记为完成
为什么 co_return 42 编译通过却拿不到结果
因为协程对象(如 Task)本身不自动暴露返回值——你得显式设计获取方式。常见漏掉的环节:
- 没实现
Task::result()成员函数去读promise.result_ - 协程还没
resume()到final_suspend就调用result(),此时result_可能未初始化 - 用了
std::coroutine_handle<promise_type></promise_type>但没检查handle.done() == true就访问 promise - 多线程环境下未加锁读写 promise 成员(
result_不是原子的)
安全读取模式通常是:coro.resume(); assert(coro.handle.done()); int x = coro.result();
真正麻烦的从来不是 co_return 这行语法,而是 promise 的内存布局、生命周期绑定和结果提取时机——这些地方一错,调试时看到的往往只是段错误或随机值,而不是清晰的编译错误。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











