std::fill的作用是将指定范围内的所有元素统一赋为同一固定值,它不依赖索引或序列逻辑,仅执行重复赋值操作;因此结果必为全相同值,若需递增序列应改用std::iota。
用
初始化数组时,为什么赋值后全是同一个值?
的作用就是把一段内存区域统一设为某个固定值,它不生成序列、不依赖索引,只做“复制粘贴”式填充。如果你期望初始化为
却写了
,那会出错——
只求值一次,所有位置都填了初始的
。
正确做法是明确区分“单值填充”和“序列填充”场景:
填充全零或全 -1:直接用
或
想填递增序列?别硬套
,换
对
使用时注意传迭代器:
,不能传
本身
原始数组(如
)可直接用指针:
用
填充递增序列,起始值填错了怎么办?
从指定起始值开始,按
操作逐个赋值,它不检查类型是否支持自增,也不做越界保护。常见翻车点:
起始值类型和容器元素类型不匹配:比如用
去填
,可能溢出或隐式截断
填
数组时忘了符号性:
没问题,但
在
是
的平台会绕成大正数
对空容器调用会静默失败(无效果),建议加
或先判大小
想填步长非 1 的等差序列?
不支持,得手写循环或用
+ lambda
和
在 vector 与原生数组上的调用写法差异
两者都依赖迭代器,但传参方式因类型而异,容易混淆:
C知道
CSDN推出的一款AI技术问答工具
下载
立即学习
“
C++免费学习笔记(深入)
”;
→
或
→
或
→ 必须用
/
,不能用
;
万不得已用
?仅限 POD 类型且填 0 或全字节相同值(如
),其他一律避免
性能与兼容性:C++11 之后哪些写法要特别注意?
和
自 C++98 就存在,但实际使用中几个细节影响跨编译器行为:
Clang 15+ 对
在
下可能做激进优化,若起始值来自未初始化变量,结果不可预测
MSVC 2019 默认开启
时,对窄类型(如
)传入
起始值会警告,建议显式
用在 constexpr 上下文?C++20 起
和
都是
,但必须确保容器本身是字面量类型且生命周期允许(如
)
批量初始化千万级数组时,
和
性能几乎一致,都是 O(N);真瓶颈往往在内存分配(如
)而非填充本身
最常被忽略的是:这两个函数都不负责内存分配。传入未分配/未构造的指针,或者对
用了
却没
,就会写到野地址——错误不报在
行,而爆在后续访问时。
std::fillstd::fill{0,1,2,3,4}std::fill(arr, arr+5, i++)i++istd::fill(arr, arr+N, 0)std::fill(v.begin(), v.end(), -1)fillstd::iotastd::arraystd::fill(a.begin(), a.end(), 42)aint arr[10]std::fill(arr, arr+10, 7)std::iotastd::iota++unsigned int start = 0std::vectorcharstd::iota(buf, buf+26, 'a')std::iota(buf, buf+26, -10)charunsignedassert(!v.empty())iotastd::generatefilliotastd::vector v(5); std::fill(v.begin(), v.end(), 9)std::iota(v.begin(), v.end(), 100)int arr[5];std::fill(arr, arr+5, 9)std::iota(arr, arr+5, 100)std::array a; a.begin()a.end()astd::fill(a.begin(), a.end(), 9)memsetmemset(arr, 0, sizeof(arr))filliotastd::iota__builtin_assume/permissive-int8_t*intstatic_caststd::fillstd::iotaconstexprconstexpr std::arrayfilliotavector::resizevectorreserveresizefill