新闻中心
c++如何利用协程实现一个生成器(Generator)_c++ co_yield的使用
C++20通过协程实现生成器,利用co_yield暂停函数并返回值,配合promise_type和coroutine_handle管理状态,可构建如斐波那契数列的惰性序列,支持类似Python生成器的惰性求值行为。

C++20 引入了协程(Coroutines)支持,使得我们可以用 co_yield 实现类似 Python 中的生成器(Generator)。通过协程,函数可以暂停执行并返回一个值,之后从中断处继续运行。这种机制非常适合实现惰性求值的序列,也就是“生成器”。
1. 生成器的基本结构
要实现一个生成器,我们需要定义一个返回类型,该类型满足协程的接口要求,通常包括 promise_type、get_return_object、initial_suspend、final_suspend 和 unhandled_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健康云开放平台
专注于健康医疗垂直领域的AI技术开放平台
113
查看详情
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_suspend用suspend_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快捷键面板


2025-12-04
浏览次数:次
返回列表
;& gen.next(); ++i) {
std::cout << gen.value() << " ";
}
std::cout << std::endl;
return 0;
}