首页 > 后端开发 > C++ > 正文

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

下次还敢
发布: 2025-12-04 12:34:02
原创
159人浏览过
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 的函数来生成一系列值。

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

蚂蚁PPT
蚂蚁PPT

AI在线智能生成PPT

蚂蚁PPT 113
查看详情 蚂蚁PPT
Generator fibonacci() {
    int a = 0, b = 1;
    while (true) {
        co_yield a;
        int tmp = a + b;
        a = b;
        b = tmp;
    }
}
登录后复制

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

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的使用的详细内容,更多请关注php中文网其它相关文章!

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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