0

0

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

裘德小鎮的故事

裘德小鎮的故事

发布时间:2025-12-25 10:42:34

|

393人浏览过

|

来源于php中文网

原创

c++20协程是可挂起恢复的函数,需手动实现promise_type、awaiter和返回类型三要素;示例generator通过co_yield实现懒加载整数生成,强调initial_suspend、final_suspend及生命周期管理。

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

协程不是线程,也不启动新执行流,它是一种可挂起、可恢复的函数,用于简化异步逻辑、生成器、状态机等场景。C++20 协程是语言级支持,但需要手动实现协程桩(promise type)、awaiter 和返回类型——不依赖运行时库,但也意味着不能直接“开箱即用”。

基础结构:三要素缺一不可

每个协程必须有:

  • 返回类型:需定义 promise_type 嵌套类,并提供 get_return_object()initial_suspend()final_suspend()return_void()(或 return_value())等接口;
  • 挂起点:使用 co_await 表达式,其操作数需满足 awaiter 要求(含 await_ready()await_suspend()await_resume());
  • 挂起关键词co_return(结束协程)、co_await(挂起等待)、co_yield(挂起并产出值,常用于 generator)。

最简可运行示例:一个懒加载的整数生成器

下面是一个能逐次产出 0、1、2 的协程 generator(类似 Python 的 yield):

// 编译需支持 C++20:g++-11+ / clang++-13+,加 -std=c++20
#include <iostream>
#include <coroutine>
#include <memory>

template<typename T>
struct Generator {
  struct promise_type;
  using handle_type = std::coroutine_handle<promise_type>

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

  explicit Generator(handle_type h) : coro_(h) {}
  Generator(const Generator&) = delete;
  Generator& operator=(const Generator&) = delete;
  Generator(Generator&& rhs) noexcept : coro_(rhs.coro_) { rhs.coro_ = nullptr; }
  Generator& operator=(Generator&& rhs) noexcept {
    if (this != &rhs) {
      if (coro_) coro_.destroy();
      coro_ = rhs.coro_;
      rhs.coro_ = nullptr;
    }
    return *this;
  }
  ~Generator() { if (coro_) coro_.destroy(); }

  bool next() {
    if (!coro_ || coro_.done()) return false;
    coro_.resume();
    return !coro_.done();
  }
  T value() const { return coro_.promise().current_value; }

private:
  handle_type coro_;
};

Generator<int> counter() {
  co_yield 0;
  co_yield 1;
  co_yield 2;
}

int main() {
  auto g = counter();
  while (g.next()) {
    std::cout << g.value() << '\n';
  }
  // 输出:0\n1\n2
}

关键点说明

这段代码展示了协程最核心的协作模式:

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

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

下载

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

  • co_yield 触发 promise_type::yield_value(),保存值并挂起;
  • Generator::next() 调用 resume() 恢复执行,直到下次挂起或结束;
  • initial_suspend() 设为 suspend_always,让协程创建后不自动运行(惰性求值);
  • final_suspend() 也设为 suspend_always,防止协程结束后自动销毁 promise,方便外部安全读取结果。

常见误区提醒

初学容易踩坑的地方:

  • 忘记在 ~Generator 中调用 coro_.destroy() → 内存泄漏;
  • 把协程句柄(coroutine_handle)复制多次却不管理生命周期 → 悬空指针;
  • 误以为 co_await 等价于“异步等待” → 它只是语法糖,行为完全由 awaiter 决定(可以立刻返回,也可以调度到线程池);
  • 没处理 unhandled_exception() → 协程内抛异常会导致程序终止。

基本上就这些。协程本身不难理解,难点在于设计清晰的协程类型契约。建议从 generator 入手,再过渡到 async/await 风格的 task 类型(如 Task<int></int>),逐步掌握 suspend/resume 的控制权。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

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

930

2023.08.02

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

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

602

2024.08.29

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

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

294

2025.08.29

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

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

212

2025.08.29

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

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

1800

2023.10.19

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

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

593

2025.10.17

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

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

2341

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

45

2026.01.19

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

33

2026.03.04

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 4.8万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.8万人学习

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

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