C++协程和线程的区别?详细介绍一下C++协程

时间:2025-03-30 07:39:02
  • #include <iostream>
  • #include <coroutine>
  • // 定义一个生成器类型,用于返回协程函数的对象
  • template<typename T>
  • struct generator {
  • // 定义一个承诺类型,用于控制协程的行为
  • struct promise_type {
  • // 保存协程产生的值
  • T value;
  • // 生成协程函数的返回对象
  • generator get_return_object() {
  • // 从承诺对象中获取协程句柄
  • return generator{ std::coroutine_handle<promise_type>::from_promise(*this) };
  • }
  • // 表示协程启动后不立即挂起
  • std::suspend_never initial_suspend() {
  • return {};
  • }
  • // 表示协程终止后不再恢复
  • std::suspend_never final_suspend() noexcept {
  • return {};
  • }
  • // 处理协程的返回值
  • void return_void() {}
  • // 处理协程的异常
  • void unhandled_exception() {
  • std::terminate();
  • }
  • // 保存协程的产生的值
  • std::suspend_always yield_value(T val) {
  • value = val;
  • return {};
  • }
  • };
  • // 保存协程句柄
  • std::coroutine_handle<promise_type> handle;
  • // 构造函数,从协程句柄初始化
  • explicit generator(std::coroutine_handle<promise_type> h) : handle(h) {}
  • // 析构函数,销毁协程
  • ~generator() {
  • if (handle) {
  • handle.destroy();
  • }
  • }
  • // 生成器不能被拷贝,只能被移动
  • generator(const generator&) = delete;
  • generator& operator=(const generator&) = delete;
  • generator(generator&& other) noexcept : handle() {
  • = nullptr;
  • }
  • generator& operator=(generator&& other) noexcept {
  • handle = ;
  • = nullptr;
  • return *this;
  • }
  • // 返回协程产生的值
  • T value() const {
  • return handle.promise().value;
  • }
  • // 恢复协程的执行
  • void resume() {
  • handle.resume();
  • }
  • // 判断协程是否结束
  • bool done() const {
  • return handle.done();
  • }
  • };
  • // 定义一个协程函数,返回一个生成器对象,用于生成斐波那契数列
  • generator<int> fibonacci(int n) {
  • int a = 0, b = 1;
  • for (int i = 0; i < n; i++) {
  • co_yield a; // 挂起协程,并产生一个值
  • auto tmp = a;
  • a = b;
  • b = tmp + b;
  • }
  • }
  • int main() {
  • // 调用协程函数,得到一个生成器对象
  • auto gen = fibonacci(10);
  • // 循环访问生成器产生的值,直到协程结束
  • while (!gen.done()) {
  • std::cout << gen.value() << " "; // 输出协程产生的值
  • gen.resume(); // 恢复协程的执行
  • }
  • std::cout << std::endl;
  • return 0;
  • }