std::generate需预分配容器空间并用mutable lambda维持状态,不支持自动扩容或默认只读捕获;generate_n配合back_inserter可动态填充,但需注意异常安全与类型匹配。

std::generate 填充 vector 的基本用法
直接调用 std::generate 时,它不会自动知道容器大小,必须显式提供迭代器范围;最常见错误是传入空 vector 的 begin() 和 end(),结果什么也不填——因为范围长度为 0。
- 先确保容器已分配空间:用
resize()或构造时指定大小 - 生成器函数(或 lambda)每次被调用时返回一个新值,不带参数
-
std::generate不负责内存管理,只写入已有位置
std::vector<int> v(5); // 必须先有 5 个元素
std::generate(v.begin(), v.end(), [n = 0]() mutable { return ++n; });
// v 现在是 {1, 2, 3, 4, 5}lambda 捕获与 mutable 的必要性
如果想让生成器“记住”状态(如递增计数、轮询数组),必须用 mutable 修饰 lambda,否则捕获的变量默认只读。不加 mutable 会导致编译失败,错误信息类似:assignment of read-only variable。
- 按值捕获(
[n = 0])适合初始化状态 - 按引用捕获(
[&counter])适合复用外部变量,但要注意生命周期 - 无捕获 lambda(如
[] { return rand(); })最安全,但无法维持上下文
int seed = 10;
std::vector<std::string> words = {"a", "b", "c"};
std::vector<std::string> result(4);
std::generate(result.begin(), result.end(), [&words, &seed]() mutable {
seed = (seed * 1103515245 + 12345) & 0x7fffffff;
return words[seed % words.size()];
});和 std::generate_n 的关键区别
std::generate 依赖迭代器范围长度,std::generate_n 显式接受数量参数,更适合配合 back_inserter 动态扩展容器——但注意:std::generate 本身不支持 back_inserter,强行传入会编译失败,报错含 no match for operator=。
- 用
std::generate_n+std::back_inserter填充变长容器 - 用
std::generate+ 预分配空间 更高效(避免多次 realloc) -
generate_n返回的是末尾迭代器,可用于链式操作
std::vector<int> v;
v.reserve(3); // 提升效率,但不改变 size
std::generate_n(std::back_inserter(v), 3, []{ static int i = 0; return i++; });
// v 是 {0, 1, 2}填充自定义类型与注意事项
对 class 类型使用 std::generate,要求生成器返回可赋值给容器元素类型的对象,且该类型需支持拷贝或移动赋值。若类无默认构造函数,预分配空间时不能用 vector<t>(n)</t>,得改用 vector<t> v; v.resize(n)</t> —— 否则编译报错:call to implicitly-deleted default constructor。
立即学习“C++免费学习笔记(深入)”;
- 确保生成器返回值类型与容器 value_type 完全匹配(含 const/volatile 限定)
- 避免在生成器中抛异常,
std::generate不做异常安全保证,可能留下部分修改状态 - 多线程环境下不要共享同一生成器实例(除非内部同步)
struct Point { int x, y; Point(int x=0, int y=0):x(x),y(y){} };
std::vector<Point> pts;
pts.resize(2); // 不能用 vector<Point>(2),因 Point 无默认构造?实际有,但若删掉默认构造就得用 resize + value-arg
std::generate(pts.begin(), pts.end(), [i=0]() mutable {
return Point{i++, i*10};
});真正容易卡住的地方是:以为 std::generate 能像 Python 的 list.extend 那样自动扩容,或者忽略 lambda 默认不可变这个硬性约束。











