std::fill仅执行按值赋值,不调用构造函数、不初始化未定义内存、不检查迭代器边界;对POD类型安全高效,对string等类类型调用赋值运算符,不能用于未初始化的栈数组。

std::fill 填什么、不填什么
std::fill 只负责按值拷贝填充,不调用构造函数(对类类型);它不初始化未定义内存,也不检查边界。你传给它的迭代器范围必须合法,否则行为未定义。
常见错误现象:std::fill 后访问数组发现值没变,或程序崩溃——大概率是迭代器范围写错了,比如把 end() 写成 begin() + size 却忘了数组实际长度不够。
- 对
int数组、double数组等 POD 类型,std::fill安全高效 - 对
std::string数组,它会调用每个元素的赋值运算符,不是默认构造,已有内容会被覆盖 - 不能用它“初始化”栈上未定义的局部数组(如
int a[10]),因为那块内存本身还没被赋予确定状态;std::fill是赋值,不是初始化
std::fill 和 memset 的关键区别
别看到“快速赋值”就下意识换 memset。memset 按字节设值,只适合 char、unsigned char 或能用 0/0xFF 全字节表示的 POD 类型(比如全 0 的 int)。对 double 填 0.0 可以用 memset(arr, 0, sizeof(arr)),但填 3.14 就完全不行。
std::fill 按对象语义赋值,安全通用,编译器通常能优化成接近 memset 的效率(尤其填 0 时)。
立即学习“C++免费学习笔记(深入)”;
- 填
0:两者性能差异极小,优先选std::fill,语义清晰 - 填非零整数(如
42):memset会错——它把每个字节设为 42,结果int变成0x2a2a2a2a,不是 42 - 填浮点数、自定义结构体:只能用
std::fill
vector 和原生数组怎么填才不出错
对 std::vector,直接用 begin()/end() 最稳妥;对 C 风格数组,必须手动计算尾后指针,容易漏掉 +1 或搞反长度单位。
示例:
int arr[5]; std::fill(arr, arr + 5, 99); // ✅ 正确:arr + 5 是尾后地址 std::vector<int> vec(5); std::fill(vec.begin(), vec.end(), 99); // ✅ 推荐:自动适配大小
- 别写
std::fill(arr, arr + sizeof(arr), ...)——sizeof(arr)返回字节数,不是元素个数 - 别对空
vector调用std::fill之前不检查empty()——虽然begin() == end()是安全的,但逻辑上无意义,容易掩盖扩容疏漏 - 如果数组是全局或 static,已零初始化,
std::fill仍会执行,没必要重复操作
fill_n 比 fill 少一个参数,但更易错
std::fill_n 只要起始迭代器和数量,看起来更简单,但数量错一位就是越界。而 std::fill 用两个迭代器,天然带范围校验意味(哪怕只是心理暗示)。
常见错误现象:用 fill_n(ptr, N, val) 填写了 N+1 个元素,因为 ptr 指向的位置本就不干净,或者 N 算少了 1。
- 对
vector,fill_n(v.begin(), v.size(), val)和fill(v.begin(), v.end(), val)等价,但前者多一次size()调用,且易手误写成v.capacity() - 对原生数组,
fill_n(arr, 5, val)比fill(arr, arr + 5, val)少敲两个字符,但少了一层视觉校验:你没法一眼看出arr + 5是否真在合法内存内 - 当数量来自运行时变量时,务必确认该变量 ≤ 容器实际容量,
fill_n不做任何检查
std::fill,而是没想清楚“这块内存到底归谁管、有没有被初始化过、迭代器算得对不对”。










