实现一个简单的生成器
构建一个能够惰性地产生值的生成器协程
实现一个简单的生成器 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。
作为协程的生成器
生成器是一种逐个产生值的协程。每次调用生成器都会产生下一个值,然后暂停。
生成器类型
定义一个包含嵌套 promise_type 的类。编译器使用它来管理协程的状态。
template <typename T>
struct Generator {
struct promise_type {
T 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 {}; }
void return_void() {}
std::suspend_always yield_value(T value) {
current_value = value;
return {};
}
void unhandled_exception() { std::terminate(); }
};
std::coroutine_handle<promise_type> h;
// ... constructors, destructor, next() ...
};使用生成器
定义完成后,生成器的使用方式与 Python 的 yield 类似。
Generator<int> counting() {
int n = 0;
while (true) co_yield n++;
}
auto g = counting();
for (int i = 0; i < 5; ++i) {
std::cout << g.next() << " ";
}
// 0 1 2 3 4协程句柄
编译器会返回一个 std::coroutine_handle。它表示已暂停的协程;您可以调用 resume()、destroy(),或检查 done()。
暂停点
每个 co_yield 都会暂停协程。当调用方调用 resume() 时,执行会继续,直到下一个暂停点或协程结束。
initial_suspend 和 final_suspend
两个自定义点:
initial_suspend— 返回suspend_always表示惰性启动;返回suspend_never表示立即启动final_suspend— 控制清理。为确保正确销毁,通常返回suspend_always
C++23 std::generator
C++23 在 <generator> 中加入了 std::generator。对于常见情况,您不再需要手动编写该类型。
#include <generator>
std::generator<int> counting() {
int n = 0;
while (true) co_yield n++;
}基于范围的 for 循环
如果生成器类型支持 begin/end,基于范围的 for 循环就可以直接使用。
for (int x : counting()) {
if (x >= 10) break;
std::cout << x;
}拉取语义与推送语义
生成器是基于拉取的,由调用方驱动迭代。基于推送的协程则是异步任务。
使用场景
生成器非常适合:
- 惰性序列(斐波那契数、素数、逐行读取文件)
- 无需物化即可处理流式数据
- 遍历树状结构
内存方面的考虑
默认情况下,协程帧会分配在堆上。如果允许内联,编译器可能会省略这次分配;在性能重要时请进行测量。
值得探索的库
学习时,Lewis Baker 编写的 cppcoro 提供了文档完善的生成器和任务类型。Boost.Asio 提供适合协程的 I/O。从 C++23 开始,标准库也提供了相关支持。
快速检查
C++23 标准库中用于生成器协程的类型是什么?
小结
生成器协程使用 co_yield 惰性地产生值。请通过包含 promise_type 的类来实现它。C++23 将 std::generator 标准化。生成器非常适合惰性序列和流式处理。
常见问题解答
「实现一个简单的生成器」课时是免费的吗?
是的 — 「实现一个简单的生成器」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。
「实现一个简单的生成器」这节课中我会学到什么?
构建一个能够惰性地产生值的生成器协程 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C++ Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「实现一个简单的生成器」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C++ Academy 课中编写并运行代码吗?
能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。