std::fill填充原生数组需传入指针范围如arr与arr+n,不可只传数组名;对vector/array则用.begin()/.end();注意异常安全、类型要求及与std::fill_n的区别。

std::fill 填充原生数组时必须传入指针范围,不能直接传数组名
数组名在多数上下文中会退化为指向首元素的指针,但 std::fill 需要两个迭代器(或指针)构成的左闭右开区间。直接传 arr 会被当作 int*,但你还需要明确结束位置。
常见错误是写成 std::fill(arr, 5, 0)(参数个数错)或 std::fill(arr, arr + 5, 0) 却忘了数组长度实际是 5 —— 若写成 arr + sizeof(arr) 就完全错了,因为 sizeof(arr) 返回字节数,不是元素个数。
- 正确做法:用
std::fill(arr, arr + N, value),其中N是元素数量 - 更安全的做法:搭配
std::size(C++17 起)或sizeof(arr) / sizeof(arr[0]) - 示例:
int arr[5]; std::fill(arr, arr + std::size(arr), 42); // C++17
std::fill 对 vector 和 array 容器同样适用,但调用方式一致
std::fill 不关心容器类型,只认迭代器。所以对 std::vector、std::array,都用 .begin() 和 .end() 即可,语义清晰且不易出错。
std::vector<int> v(10); std::fill(v.begin(), v.end(), -1);</int>std::array<double> a; std::fill(a.begin(), a.end(), 3.14);</double>- 注意:
std::array::end()返回的是尾后迭代器,符合左闭右开要求,和原生数组的arr + N等价
填充非 POD 类型时,要求类型支持拷贝赋值,且无异常抛出更安全
std::fill 内部对每个位置执行 *it = value。如果 T 的拷贝赋值运算符可能抛异常(比如某些自定义类),而你又在无异常保证的上下文中使用(如析构函数),就可能出问题。
- 内置类型(
int、double)、std::string(C++11 起提供强异常安全保证)通常没问题 - 若类型仅支持移动赋值、不支持拷贝赋值,则
std::fill编译失败 —— 此时应改用std::fill_n配合移动构造,或用循环 - 性能上:对 trivial 类型(如
int),编译器常将std::fill优化为memset或向量化指令;但不要依赖这点,它只是优化,不是标准保证
别和 std::fill_n 混用:后者按数量填充,前者按范围填充
容易混淆的是 std::fill_n:它接收一个起始迭代器和一个数量 n,而不是结束迭代器。两者语义不同,选错会导致越界或漏填。
- 错误示例:
std::fill_n(arr, std::size(arr), 99)是对的;但若写成std::fill_n(arr, arr + 5, 99)会编译失败(第二个参数类型应为size_t,不是指针) - 关键区别:
std::fill(first, last, val)→ 范围驱动;std::fill_n(first, n, val)→ 数量驱动 - 当只有起始地址和长度信息(比如从 C API 拿到
int* p和size_t len),用std::fill_n(p, len, val)更自然,避免手动算p + len
最常被忽略的一点:原生数组的大小信息在传递给函数后就丢失了。如果你把数组以参数形式传入函数,sizeof(arr) 会变成指针大小。这时候 std::fill 必须依赖外部传入的长度,或者改用 std::span(C++20)来携带尺寸信息。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











