std::fill用于批量赋相同值,需确保迭代器范围不越界;std::iota仅支持+1递增序列,不支持自定义步长或倒序,二者性能差异源于编译器优化程度与内存访问模式。

用 std::fill 批量赋相同值,注意迭代器范围别越界
std::fill 是最直接的批量初始化手段,适合给数组/容器所有元素设为同一值。它不关心类型是否可构造,只要支持赋值即可。
常见错误是传入裸指针时长度算错:std::fill(arr, arr + size, 0) 中 size 必须是实际元素个数,不是字节数;若用 sizeof(arr)(在函数内传参后失效)会崩。
- 对
std::vector:用v.begin()和v.end()最安全 - 对 C 风格数组:确保
arr + N中N是编译期可知大小,或用std::size(arr)(C++17 起) - 性能上,
std::fill通常被编译器优化为memset(对char、int等 POD 类型),实测比手写 for 循环快 10%–30%
用 std::iota 填递增序列,起始值和步长得自己控制
std::iota 本质是“从某值开始,逐个加 1”,不是通用等差数列工具。它只支持 +1 步进,不能设公差,也不能倒序(除非重载 operator++)。
典型误用:std::iota(arr, arr + N, 100) 填的是 100, 101, 102, ...,不是 100, 200, 300...。真要等差得自己写循环或配合 std::transform。
立即学习“C++免费学习笔记(深入)”;
- 输入迭代器必须支持前缀 ++(
int*、std::vector::iterator都行) - 底层无特殊 SIMD 优化,纯线性递增,N 超过 10⁶ 时比
std::fill慢约 15%(因每次都要计算新值) - 对
std::array或栈数组,std::iota(arr, arr + std::size(arr), 0)是简洁写法
性能实测差异主要在内存访问模式和编译器优化程度
在 GCC 13 + -O2 下,对 10M 个 int 数组:
-
std::fill平均耗时 3.2 ms —— 编译器大概率转成rep stosd或向量化 store -
std::iota平均耗时 4.8 ms —— 每次迭代含 load-modify-store,且依赖前一次结果,无法并行 - 手写
for (int i = 0; i 耗时 3.5 ms,略慢于 <code>std::fill(少一层抽象但没触发 memset 优化)
注意:若元素类型是自定义类(如 struct Vec3 { float x,y,z; };),std::fill 调用的是拷贝赋值,std::iota 还要求该类型重载 operator++,否则编译失败 —— 这点容易被忽略。
复杂场景下别硬套 iota,优先考虑 std::generate 或范围适配器
需要非 +1 序列(如偶数、平方数、随机数)时,std::iota 就不够用了。此时 std::generate 更灵活,配合 lambda 可控性强:
std::generate(arr, arr + N, [n = 0]() mutable { return (n += 2); }); // 偶数序列C++20 范围库还能进一步简化:
auto rng = views::iota(0) | views::transform([](int i) { return i * i; }) | views::take(N);
std::copy(rng.begin(), rng.end(), arr);但要注意:这种写法在小数组上反而更慢(临时对象+迭代器开销),只适合逻辑复杂且 N 较大、可 pipeline 优化的场景。



















