c++20协程是什么 c++ coroutine入门使用【前沿】

C++20协程是编译器支持的协作式执行机制,通过co_await、co_yield、co_return识别,需自定义返回类型及promise_type,并遵循awaiter协议实现挂起与恢复。

C++20协程不是“线程”或“语法糖”,而是一套编译器支持的、用户可定制的协作式执行机制。它让函数能中途暂停、保存状态、稍后从中断点恢复,整个过程不依赖操作系统调度,开销远低于线程,也比回调嵌套更直观。

协程怎么识别?三个关键字就够了

只要函数体内出现以下任意一个,编译器就把它当作协程:

  • co_await:挂起当前协程,等待某个操作完成(比如网络响应、定时器到期);
  • co_yield:产出一个值并挂起,常用于生成器(如逐个返回斐波那契数);
  • co_return:结束协程,并把结果交给调用方(可带值,也可不带)。

必须定义的返回类型和 promise_type

协程不能直接返回 intvoid,必须返回一个自定义类型(如 taskgenerator),且该类型内部要嵌套定义 promise_type

promise_type 是协程行为的“控制中心”,至少需实现:

  • get_return_object():构造并返回协程句柄关联的对象(比如 task{handle});
  • initial_suspend():决定协程一启动就运行(suspend_never),还是先挂起(suspend_always);
  • final_suspend():协程结束时是否挂起(影响资源清理时机);
  • return_value(T)return_void():接收 co_return 的值;
  • unhandled_exception():捕获未处理异常(建议调用 std::terminate 或记录)。

co_await 背后是 awaiter 协议

co_await expr 不是直接等系统调用,而是要求 expr 类型满足 awaiter 接口:

  • await_ready():快速判断是否还需真挂起(比如缓冲区已有数据,就跳过挂起);
  • await_suspend(coroutine_handle):真正挂起时调用,通常注册回调(如投递到线程池、io_uring、epoll);
  • await_resume():恢复后执行,返回给 co_await 表达式的值。

典型入门写法:一个最简 task

不用第三方库,也能跑通基本流程:

struct task {
  struct promise_type {
    task get_return_object() { return {}; }
    std::suspend_never initial_suspend() { return {}; }
    std::suspend_always final_suspend() noexcept { return {}; }
    void return_void() {}
    void unhandled_exception() { std::terminate(); }
  };
};

task my_coro() {
  std::cout << "start\n";
  co_await std::suspend_always{}; // 主动挂起一次
  std::cout << "resumed\n";
  co_return;
}

调用后协程立即执行到 co_await 挂起;之后需手动调用 coroutine_handle::resume() 才会继续——这就是“可控暂停”的本质。