新闻中心

c++如何利用协程实现一个生成器(Generator)_c++ co_yield的使用

2025-12-04
浏览次数:
返回列表
C++20通过协程实现生成器,利用co_yield暂停函数并返回值,配合promise_type和coroutine_handle管理状态,可构建如斐波那契数列的惰性序列,支持类似Python生成器的惰性求值行为。

c++如何利用协程实现一个生成器(generator)_c++ co_yield的使用

C++20 引入了协程(Coroutines)支持,使得我们可以用 co_yield 实现类似 Python 中的生成器(Generator)。通过协程,函数可以暂停执行并返回一个值,之后从中断处继续运行。这种机制非常适合实现惰性求值的序列,也就是“生成器”。

1. 生成器的基本结构

要实现一个生成器,我们需要定义一个返回类型,该类型满足协程的接口要求,通常包括 promise_typeget_return_objectinitial_suspendfinal_suspendunhandled_exception 等组件。

下面是一个简单的整数生成器示例:

#include <coroutine>
#include <iostream>

struct Generator {
    struct promise_type {
        int current_value;

        // 返回生成器对象
        Generator get_return_object() {
            return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
        }

        // 协程开始时是否挂起
        std::suspend_always initial_suspend() { return {}; }

        // 协程结束时是否挂起
        std::suspend_always final_suspend() noexcept { return {}; }

        // 每次 co_yield 后挂起
        std::suspend_always yield_value(int value) {
            current_value = value;
            return {};
        }

        void return_void() {}
        void unhandled_exception() { std::terminate(); }
    };

    using handle_type = std::coroutine_handle<promise_type>;

    explicit Generator(handle_type h) : coro(h) {}

    ~Generator() {
        if (coro) coro.destroy();
    }

    // 移动构造和赋值
    Generator(Generator&& other) noexcept : coro(other.coro) {
        other.coro = nullptr;
    }
    Generator& operator=(Generator&& other) noexcept {
        if (this != &other) {
            if (coro) coro.destroy();
            coro = other.coro;
            other.coro = nullptr;
        }
        return *this;
    }

    // 删除拷贝操作
    Generator(const Generator&) = delete;
    Generator& operator=(const Generator&) = delete;

    // 检查是否还有值
    bool next() {
        if (!coro || coro.done()) return false;
        coro.resume();
        return !coro.done();
    }

    // 获取当前值
    int value() const {
        return coro.promise().current_value;
    }

private:
    handle_type coro;
};

2. 使用 co_yield 定义生成函数

有了上面的 Generator 类型后,就可以写一个使用 co_yield 的函数来生成一系列值。

Generator fibonacci() {
    int a = 0, b = 1;
    while (true) {
        co_yield a;
        int tmp = a + b;
        a = b;
        b = tmp;
    }
}

这个函数会无限生成斐波那契数列中的每一项。每次调用 co_yield 时,函数会保存状态并返回当前值,下次从下一条语句继续执行。

Health AI健康云开放平台 Health AI健康云开放平台

专注于健康医疗垂直领域的AI技术开放平台

Health AI健康云开放平台 113 查看详情 Health AI健康云开放平台

3. 遍历生成器的值

使用前面定义的 Generator,我们可以像这样遍历前几个斐波那契数:

int main() {
    auto gen = fibonacci();

    for (int i = 0; i < 10 &;& gen.next(); ++i) {
        std::cout << gen.value() << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果:

0 1 1 2 3 5 8 13 21 34

4. 关键点说明

  • co_yield 表达式:将值传给生成器,并挂起协程。下次恢复时从它后面继续执行。
  • std::suspend_always / std::suspend_never:控制协程在启动或结束时是否挂起。一般 initial_suspendsuspend_always 可以延迟执行,直到第一次 resume。
  • promise_type 是核心,它决定了协程的行为。
  • 协程句柄(coroutine_handle) 允许外部控制协程的生命周期和执行流程。

基本上就这些。C++ 的协程比 Python 更底层,需要手动管理一些细节,但灵活性更高。一旦封装好 Generator 类,使用起来就很接近传统意义上的生成器了。

以上就是c++++如何利用协程实现一个生成器(Generator)_c++ co_yield的使用的详细内容,更多请关注其它相关文章!


# 句柄  # seo框架推荐  # 福清推广营销费用多少钱一个月  # 房地产网站建设策略  # 山东济南微信营销seo推广运营  # 西湖区网站优化哪里好  # 营销推广赋能方案设计图  # 雪津啤酒营销推广方式  # 青海律师网站建设  # 脐橙seo描述  # 网站建设营销分析案例  # 可以用  # 求值  # python  # 几个  # 是一个  # 结束时  # 管理器  # 下次  # 遍历  # 挂起  # stream  # ios  # c++  # ai 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 汽水音乐在线解析 汽水音乐在线解析入口  C#如何安全地从用户上传的XML文件中读取数据? 验证与清理策略  Python自定义类排序:解决lambda键值访问TypeError的实践指南  一加手机电池耗电快怎么办_一加手机电池耗电快的解决方法  Python模块化编程:有效管理依赖与避免循环引用  免费抖音短视频入口_抖音网页版短视频免费通道  c++ 命名空间怎么用 c++ namespace使用指南  Node.js CSV 数据处理:基于字段空值条件过滤整条记录的策略  sublime如何优雅地处理行尾空格_sublime自动清理多余空白字符配置  excel如何生成目录 excel一键生成工作表目录超链接  谷歌浏览器浏览体验优化_谷歌浏览器新版直连永久可用提示  怎样在Excel中做仪表盘_Excel仪表盘设计与关键指标展示方法  Golang如何处理RPC请求负载均衡_Golang RPC请求负载均衡策略与实践  AO3镜像入口大全 AO3网页版内容访问全集  极兔快递快件信息查询系统 极兔快递官网运单号追踪  iwriter统一登录平台 iwrite账号密码登录页面  MinIO大规模对象列表性能瓶颈深度解析与外部元数据管理策略  一加Ace 6T实拍样张首次公布!李杰:主摄实力完全看齐4K档性能旗舰  Win10如何恢复误删的快捷方式_Win10重建常用软件快捷方式  解决Python logging 中 datefmt 导致时间戳固定不变的问题  JUnit5/Mockito:优雅测试内部依赖与异常处理的实践  动漫共和国防屏蔽稳定域名-动漫共和国官方正版直达通道  必由学在线入口 必由学网页版快速登录入口  夸克AO3官网入口_AO3镜像网站2025推荐  J*aScript井字棋(Tic-Tac-Toe)核心交互逻辑实现教程  poki网页游戏推荐_poki免费游戏平台入口  照顾宝贝2小游戏免费秒玩入口  Python中高效访问嵌套字典与列表中的键值对  企业名称高精度匹配:N-gram方法在结构相似性分析中的应用  文心一言怎样用批量生成做多版文案_文心一言用批量生成做多版文案【批量创作】  J*aScript数据结构转换:将对象数组按类别分组  机器学习中对数变换预测结果的反向还原  单射、满射与双射的关系 一文理清所有逻辑  Golang如何实现Web接口签名验证_Golang Web接口签名校验开发方法  qq游戏手机版下载安装_qq游戏移动端入口  中兴Axon42Ultra怎样在文件App筛图_iPhone中兴Axon42Ultra文件App筛图【图片筛选】  快速CSGO开箱网站指南 CSGO开箱平台推荐  Centos/Linux 系统下安装 composer 的完整步骤  小红书怎么解除第三方平台绑定_小红书多平台登录解绑方法介绍  Fabric Mod开发:在1.19.3+版本中正确添加自定义物品并管理物品组  C++如何操作注册表_Windows平台下C++读写注册表的API函数详解  PHP表单数据传递:如何通过隐藏输入字段获取动态ID  Golang并发任务中错误如何聚合_Golang goroutine error收集方式  基于动态规划的房屋花卉种植最小成本算法详解  怎么在浏览器上运行HTML文件_浏览器运行HTML文件技巧【技巧】  电脑安装程序提示“错误1722”怎么办_Windows Installer服务问题解决【教程】  美团外卖商家服务中心入口 美团商家版官网入口  SteamMachine定价或为699美元 大家想入手吗?  css链接悬停下划线样式如何自定义_使用::after结合content和transition  Mac怎么使用表情符号_Mac Emoji快捷键面板 

搜索