C++20协程通过co_await、co_yield、co_return实现暂停与恢复,提升异步代码可读性。1. 协程需定义promise_type控制行为;2. 使用coroutine_handle管理生命周期;3. 通过suspend_always/suspend_never控制执行时机;4. 示例展示协程暂停、手动resume恢复的完整流程。

C++20协程是现代C++中一项重要的异步编程特性,它允许函数在执行过程中暂停并恢复,而无需阻塞线程。与传统回调或基于Future/Promise的异步模型相比,协程让异步代码看起来更像同步代码,提升可读性和维护性。要入门C++20协程,关键不是一开始就理解所有机制,而是先掌握基本语法结构和一个可运行的简单示例。
协程的基本概念与特征
C++20中的协程并不是语言层面新增的一种函数类型,而是通过特定关键字和接口约定实现的。一个函数只要使用了以下三个关键字之一:co_await、co_yield 或 co_return,就会被编译器识别为协程。
协程的核心特点是:
可以暂停(suspend)执行,并保存当前状态之后能从中断点恢复(resume)继续执行不阻塞调用它的线程(适合I/O等待、定时任务等场景)
但C++20协程是无栈协程(stackless),这意味着局部变量在挂起期间必须由运行时或框架管理,不能像有栈协程那样直接保存整个调用栈。
立即学习“C++免费学习笔记(深入)”;
必需组件:promise_type 与 awaitable
C++20协程需要用户定义一些底层类型来控制其行为,主要包括 promise_type 和满足Awaitable要求的对象。
每一个协程返回类型(比如 Task)都必须有一个嵌套的 promise_type,用于定义协程内部如何初始化、返回值处理以及最终结果获取。
下面是一个最简化的 Task 类型定义:
struct Task { struct promise_type { Task get_return_object() { return {}; } std::suspend_never initial_suspend() { return {}; } std::suspend_never final_suspend() noexcept { return {}; } void return_void() {} void unhandled_exception() {} };};
解释一下每个部分的作用:
get_return_object():协程启动时被调用,返回供外部使用的对象(这里是Task实例)initial_suspend():决定协程开始是否立即挂起。返回 std::suspend_never 表示直接运行final_suspend():协程结束时是否挂起。通常设为永不挂起以便清理资源return_void():用于没有返回值的协程(void类型)unhandled_exception():处理协程内未捕获异常
编写第一个协程示例
现在我们写一个简单的协程函数,演示如何使用 co_return 返回结果:
#include #includestruct Task {struct promise_type {Task get_return_object() { return {}; }std::suspend_never initial_suspend() { return {}; }std::suspend_never final_suspend() noexcept { return {}; }void return_void() {}void unhandled_exception() {}};};
Task hello_coroutine() {std::cout << "Hello from coroutine!n";co_return; // 触发 return_void()}
int main() {auto t = hello_coroutine();std::cout << "Coroutine was executed.n";return 0;}
这个程序输出:
Hello from coroutine!
Coroutine was executed.
说明协程立即执行,并未真正“异步”运行。这是因为我们设置了 initial_suspend 为 suspend_never。如果想延迟执行,可以改为 std::suspend_always,然后手动 resume。
支持 co_await 的简单等待示例
接下来扩展 Task 类型,让它支持 co_await 操作。我们先定义一个简单的awaiter:
auto operator co_await() noexcept { struct Awaiter { bool await_ready() const noexcept { return true; } void await_suspend(std::coroutine_handle) noexcept {} void await_resume() noexcept {} }; return Awaiter{};}
然后修改协程函数,加入 await 调用:
Task async_hello() { std::cout << "Step 1n"; co_await std::suspend_always{}; // 挂起一次 std::cout << "Resumed - Step 2n"; co_return;}
注意:即使挂起了,也需要有人去调用 handle.resume() 才能继续。完整控制协程生命周期的例子如下:
struct Task { struct promise_type; using handle_type = std::coroutine_handle;handle_type coro;Task(handle_type h) : coro(h) {}~Task() { if (coro) coro.destroy();}struct promise_type { Task get_return_object() { return Task{handle_type::from_promise(*this)}; } std::suspend_always initial_suspend() { return {}; } std::suspend_always final_suspend() noexcept { return {}; } void return_void() {} void unhandled_exception() {}};void resume() { if (coro && !coro.done()) coro.resume();}
};
使用方式:
Task my_coro() { std::cout << "Startedn"; co_await std::suspend_always{}; std::cout << "After first suspendn"; co_await std::suspend_always{}; std::cout << "Donen";}int main() {auto t = my_coro(); // 不会立刻执行t.resume(); // 第一次恢复t.resume(); // 第二次恢复return 0;}
输出:
Started
After first suspend
Done
这展示了协程真正的暂停与恢复能力。
基本上就这些。C++20协程门槛较高,但只要从最小可运行例子入手,逐步理解 promise_type、handle、suspend 控制逻辑,就能打下坚实基础。后续可学习如何结合事件循环、实现带返回值的Task、生成器(generator)等高级用法。
以上就是C++20的协程(coroutine)怎么入门_C++20协程基础语法与入门示例的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1480826.html
微信扫一扫
支付宝扫一扫