0

0

C++20的协程(Coroutines)如何使用?(入门示例)

穿越時空

穿越時空

发布时间:2025-12-29 19:42:34

|

424人浏览过

|

来源于php中文网

原创

协程是用户态可挂起恢复的函数,C++20采用无栈协程,编译器将其重写为状态机;需含co_await/co_yield/co_return之一,返回类型须定义promise_type以支持协程协议。

c++20的协程(coroutines)如何使用?(入门示例)

协程不是线程,也不依赖操作系统调度;它是用户态的、可挂起和恢复的函数,适合写异步 I/O、生成器、状态机等逻辑清晰但传统回调写法容易嵌套过深的场景。C++20 的协程是无协程(stackless),编译器会将协程函数重写为状态机,由你控制内存布局和执行时机。

第一步:识别协程函数——三个关键字缺一不可

一个函数要成为协程,必须在函数体中至少出现以下任一关键词:

  • co_await:等待某个“可等待对象”(如自定义 awaiter、std::suspend_always)
  • co_yield:产出值并挂起,常用于生成器
  • co_return:结束协程(可能触发清理或回调)

只要用了其中一个,编译器就按协程处理——自动改写函数签名、生成 promise 对象、管理状态机。注意:函数返回类型必须满足特定要求(见下一步)。

第二步:返回类型需支持协程协议——关键在 promise_type

协程函数的返回类型(比如 Generator)必须嵌套定义 promise_type,该类型负责协程生命周期的关键行为:

立即学习C++免费学习笔记(深入)”;

  • get_return_object():返回协程句柄(如 Generator 实例),供调用者接收
  • initial_suspend():决定协程启动时是否立刻挂起(常返回 std::suspend_alwaysstd::suspend_never
  • final_suspend():协程结束前是否挂起(影响资源释放时机)
  • unhandled_exception():捕获未处理异常
  • return_void() / return_value(T):对应 co_return 的不同写法

标准库没提供通用协程类型,你需要自己定义(或使用第三方如 cppcoro)。初学建议从简单生成器入手。

《PHP设计模式指南》中文版
《PHP设计模式指南》中文版

《PHP设计模式》首先介绍了设计模式,讲述了设计模式的使用及重要性,并且详细说明了应用设计模式的场合。接下来,本书通过代码示例介绍了许多设计模式。最后,本书通过全面深入的案例分析说明了如何使用设计模式来计划新的应用程序,如何采用PHP语言编写这些模式,以及如何使用书中介绍的设计模式修正和重构已有的代码块。作者采用专业的、便于使用的格式来介绍相关的概念,自学成才的编程人员与经过更多正规培训的编程人员

下载

第三步:动手写一个整数生成器(Generator

下面是最小可行示例,实现一个每次调用 next() 返回下一个斐波那契数的协程:

template
class Generator {
  struct promise_type;
  using handle_type = std::coroutine_handle

  handle_type h_;

public:
  Generator(handle_type h) : h_(h) {}
  Generator(Generator&& g) noexcept : h_(std::exchange(g.h_, {})) {}
  ~Generator() { if (h_) h_.destroy(); }

  T next() {
    h_.resume();
    return h_.promise().current_value;
  }

  struct promise_type {
    T current_value;
    std::suspend_always initial_suspend() { return {}; }
    std::suspend_always final_suspend() noexcept { return {}; }
    Generator get_return_object() { return Generator{handle_type::from_promise(*this)}; }
    void return_void() {}
    void unhandled_exception() { std::terminate(); }
    std::suspend_always yield_value(T value) {
      current_value = value;
      return {};
    }
  };
};

// 协程函数
Generator fibonacci() {
  int a = 0, b = 1;
  co_yield a;
  co_yield b;
  while (true) {
    int next = a + b;
    co_yield next;
    a = b;
    b = next;
  }
}

使用方式:

auto gen = fibonacci();
for (int i = 0; i < 10; ++i) {
  std::cout << gen.next() << " "; // 输出前10个斐波那契数
}

第四步:理解 co_await —— 自定义 awaiter 的核心三接口

当你写 co_await expr,expr 类型需提供:

  • await_ready():返回 bool,true 表示无需挂起,直接继续
  • await_suspend(handle):挂起时调用,可安排 handle 在未来某时 resume(例如投递到线程池、注册到 epoll)
  • await_resume():resume 后返回给 co_await 表达式的值

这是实现异步 I/O 的入口。例如封装一个 sleep_for awaiter,内部用 std::thread::sleep_for + std::jthread 或定时器唤醒 handle,就能写出 co_await sleep_for(500ms) 这样的代码。

不复杂但容易忽略:协程对象的内存必须手动管理(或用智能指针包装 handle),且 promise 对象默认分配在协程帧中(栈上),若需跨 suspend 持久化,得重载 operator new 做堆分配。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

311

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

517

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

48

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

188

2025.08.29

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

987

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

44

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

32

2025.12.29

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

364

2023.07.18

俄罗斯搜索引擎Yandex最新官方入口网址
俄罗斯搜索引擎Yandex最新官方入口网址

Yandex官方入口网址是https://yandex.com;用户可通过网页端直连或移动端浏览器直接访问,无需登录即可使用搜索、图片、新闻、地图等全部基础功能,并支持多语种检索与静态资源精准筛选。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1

2025.12.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Rust 教程
Rust 教程

共28课时 | 3.9万人学习

PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6.2万人学习

Git 教程
Git 教程

共21课时 | 2.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号