C++的协程生成器怎么写_C++20使用co_yield实现数据流生成器

发布时间 - 2026-01-05 00:00:00    点击率:
C++20通过co_yield实现惰性求值生成器,可按需产生数据;定义generator模板类并结合协程接口,用range函数示例展示逐值生成;通过next()和value()遍历输出1至5,适用于高效处理大量或无限序列。

C++20 引入了协程支持,使得我们可以用 co_yield 实现惰性求值的数据流生成器。这种生成器能按需产生数据,节省内存和计算资源,特别适合处理大量或无限序列的数据。

基本概念:协程与生成器

在 C++20 中,一个函数如果使用了 co_yieldco_awaitco_return,就成为协程。要实现生成器(generator),我们需要定义一个返回类型,它满足协程的接口要求,并管理协程的生命周期。

标准库目前没有内置 generator 类型,但可以自己实现一个简单的版本,或者使用第三方库如 cppcoro。下面是一个基于 C++20 的简易 generator 实现。

手写一个简单的 generator 类

我们通过定义一个名为 generator 的模板类,配合协程特性来实现数据流生成。

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

#include 
#include 

template
struct generator {
    struct promise_type;
    using handle_type = std::coroutine_handle;

    struct promise_type {
        T value_;
        bool done_ = false;

        generator get_return_object() {
            return generator(handle_type::from_promise(*this));
        }

        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }

        void return_void() {}

        std::suspend_always yield_value(const T& value) {
            value_ = value;
            return {};
        }

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

    handle_type h_;

    explicit generator(handle_type h) : h_(h) {}

    ~generator() {
        if (h_) h_.destroy();
    }

    generator(const generator&) = delete;
    generator& operator=(const generator&) = delete;

    generator(generator&& other) noexcept : h_(other.h_) {
        other.h_ = nullptr;
    }

    generator& operator=(generator&& other) noexcept {
        if (this != &other) {
            if (h_) h_.destroy();
            h_ = other.h_;
            other.h_ = nullptr;
        }
        return *this;
    }

    bool next() {
        if (!h_ || h_.done()) return false;
        h_();
        return !h_.done();
    }

    const T& value() const { return h_.promise().value_; }
};

使用 co_yield 编写数据流生成器函数

定义好 generator 后,就可以编写返回该类型的函数,并在其中使用 co_yield 来逐步输出数据。

generator range(int start, int end) {
    for (int i = start; i < end; ++i) {
        co_yield i; // 每次调用 next() 时返回一个值
    }
}

这个 range 函数不会一次性生成所有整数,而是每次迭代时才计算下一个值,实现了惰性求值。

如何使用生成器遍历数据

通过循环调用 next() 和访问 value(),可以逐个获取生成的元素。

int main() {
    auto gen = range(1, 6);

    while (gen.next()) {
        std::cout << gen.value() << ' ';
    }
    std::cout << '\n'; // 输出: 1 2 3 4 5
    return 0;
}

这段代码会依次打印从 1 到 5 的数字,每次调用 next() 触发一次协程执行,直到完成。

这种方式非常适合用于模拟无限序列、文件行读取、树遍历等场景,避免预加载全部数据。

基本上就这些。C++20 协程虽然语法稍复杂,但一旦掌握,就能写出高效、清晰的惰性数据流逻辑。注意编译时需启用 C++20 支持(如 GCC 加 -std=c++20),并且不同编译器对协程的支持程度可能略有差异。


# ai  # c++  # ios  # stream  # 标准库  # 循环  # 接口  # 遍历  # 求值  # 按需  # 是一个  # 就能  # 可以用  # 适用于  # 并在  # 这段  # 第三方 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏  Laravel如何构建RESTful API_Laravel标准化API接口开发指南  Laravel中间件如何使用_Laravel自定义中间件实现权限控制  今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】  香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南  三星网站视频制作教程下载,三星w23网页如何全屏?  Laravel怎么实现模型属性转换Casting_Laravel自动将JSON字段转为数组【技巧】  软银砸40亿美元收购DigitalBridge 强化AI资料中心布局  如何用5美元大硬盘VPS安全高效搭建个人网站?  Laravel如何处理异常和错误?(Handler示例)  JavaScript如何实现类型判断_typeof和instanceof有什么区别  北京网站制作的公司有哪些,北京白云观官方网站?  Laravel如何创建和注册中间件_Laravel中间件编写与应用流程  Laravel如何使用查询构建器?(Query Builder高级用法)  网站制作软件有哪些,制图软件有哪些?  Laravel怎么处理异常_Laravel自定义异常处理与错误页面教程  java获取注册ip实例  如何快速生成凡客建站的专业级图册?  iOS中将个别页面强制横屏其他页面竖屏  绝密ChatGPT指令:手把手教你生成HR无法拒绝的求职信  Laravel distinct去重查询_Laravel Eloquent去重方法  深圳网站制作的公司有哪些,dido官方网站?  在线制作视频网站免费,都有哪些好的动漫网站?  网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?  Gemini怎么用新功能实时问答_Gemini实时问答使用【步骤】  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】  详解CentOS6.5 安装 MySQL5.1.71的方法  Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理  Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】  JS弹性运动实现方法分析  详解Android中Activity的四大启动模式实验简述  专业商城网站制作公司有哪些,pi商城官网是哪个?  Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧  js代码实现下拉菜单【推荐】  Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理  Win11关机界面怎么改_Win11自定义关机画面设置【工具】  ,网页ppt怎么弄成自己的ppt?  Python自然语言搜索引擎项目教程_倒排索引查询优化案例  如何在服务器上配置二级域名建站?  INTERNET浏览器怎样恢复关闭标签页_INTERNET浏览器标签恢复快捷键与方法【指南】  微信小程序 input输入框控件详解及实例(多种示例)  javascript读取文本节点方法小结  大连 网站制作,大连天途有线官网?  如何用好域名打造高点击率的自主建站?  Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】  如何确保FTP站点访问权限与数据传输安全?  太平洋网站制作公司,网络用语太平洋是什么意思?  网站制作壁纸教程视频,电脑壁纸网站?  html5源代码发行怎么设置权限_访问权限控制方法与实践【指南】