std::generator是C++23协程返回类型,需编译器支持(GCC 13+/Clang 16+/MSVC 19.32+)并启用协程开关;必须用std::generator<T>显式声明返回类型,函数体含co_yield或co_return,迭代器仅满足InputIterator,对象析构则所有迭代器立即失效。

std::generator 是 C++23 协程,不是模板别名或宏
它本质是一个协程返回类型,依赖编译器对 co_yield、co_return 和协程帧的底层支持。GCC 13+(需 -std=c++23 -fcoroutines),Clang 16+(-std=c++23 -Xclang -enable-experimental-coroutines),MSVC 19.32+ 默认启用。没开协程开关会直接报错:‘co_yield’ declared in non-coroutine function。
- 必须用
std::generator<T>作为函数返回类型,不能用auto(类型不完整) - 函数体里至少出现一次
co_yield或co_return,否则编译器不认为它是协程 - 不能捕获局部变量到协程帧外——
std::generator对象可拷贝,但内部状态不可跨调用共享
怎么写一个能跑起来的最简 std::generator
重点不在“生成逻辑”,而在满足协程签名和生命周期约束。下面这个例子返回 0、1、2,每调用一次 begin() 都新建一个迭代器,每次 ++it 触发下一次 co_yield:
std::generator<int> count_to_3() {
co_yield 0;
co_yield 1;
co_yield 2;
}- 调用后不立即执行,只构造一个惰性对象;真正执行从第一次
begin()开始 - 迭代器失效规则和普通容器不同:一旦 generator 对象析构,所有其产生的迭代器立刻失效(不是悬垂,是未定义行为)
- 不能在
co_yield后写return;要用co_return(哪怕只是co_return;)来结束协程
std::generator 的迭代器不是 RandomAccessIterator
它只满足 InputIterator 要求:单向、只读、不可重复遍历。这意味着你不能用 std::sort、operator[]、std::distance(除非手动计数),也不能用 for (auto&& x : gen) 以外的方式“跳转”。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
gen.begin()每次都启动新协程实例,不是复用旧状态 - 没有
size()成员——生成器可能无限(比如斐波那契流),长度无法静态推导 - 想缓存结果?得自己用
std::vector接住:std::vector<int> v(gen.begin(), gen.end());,但要注意这会完全消费 generator
常见崩溃点:把 generator 当作普通容器传参或存储
最容易出问题的是隐式移动或意外析构。例如:
立即学习“C++免费学习笔记(深入)”;
void process(std::generator<int> g) { /* ... */ }
process(count_to_3()); // OK:临时对象绑定到右值引用,移动构造
std::generator<int> g = count_to_3(); // OK:显式移动
auto g2 = g; // 编译失败:std::generator 不可拷贝(只有移动构造/赋值)
- 成员变量里存
std::generator?危险。类析构时 generator 析构,若此时还有活跃迭代器,行为未定义 - lambda 捕获 generator 并延迟调用?不行——generator 内部资源在作用域结束时释放,捕获后调用会 crash
- 调试时用 IDE 断点停在
co_yield行,注意协程栈和普通栈分离,局部变量生命周期以协程帧为准
协程状态管理是隐式的,但破坏规则的代价很高:不是编译报错,而是运行时静默崩溃或迭代器失效后继续解引用。


















