std::ranges::fill 用于填充满足 range 概念的容器,调用形式为 std::ranges::fill(range, value),需 c++20 支持并包含 头文件,不适用于 const 容器。

std::ranges::fill 用法和基本调用方式
直接用 std::ranges::fill 填充一个范围,比传统 std::fill 更简洁,且支持所有满足 std::ranges::range 概念的容器(std::vector、std::array、原始数组、std::string 等),无需手动传迭代器对。
最常用写法就是:std::ranges::fill(range, value)。它内部自动推导 begin() 和 end(),省去手写迭代器的麻烦。
- 对
std::vector<int> v(5);</int>,直接写std::ranges::fill(v, 42);—— 不用再写v.begin(), v.end() - 对原始数组
int arr[3];,也能用std::ranges::fill(arr, 0);,编译器识别数组长度 - 对
std::string s("hello");,std::ranges::fill(s, 'x');会把每个字符变成'x'
为什么有时编译失败?常见错误和头文件依赖
std::ranges::fill 是 C++20 引入的,必须确保编译器支持 C++20 且启用了对应标准(如 -std=c++20)。否则会报 ‘ranges’ is not a namespace name 或 no member named ‘fill’ in namespace ‘std::ranges’。
- 缺头文件:必须包含
<algorithm></algorithm>,不是<ranges></ranges>(C++20 中std::ranges::fill定义在<algorithm></algorithm>) - Clang/GCC 需显式开启 C++20:GCC 10+、Clang 10+ 才完整支持;MSVC 19.28+(VS 2019 16.8+)起支持
- 别和
std::fill混用:如果误写成std::fill(v, 42)(漏掉ranges::),会触发 SFINAE 失败或编译错误,因为std::fill只接受迭代器对
与 std::fill 的性能和语义差异
二者语义完全一致:逐个赋值,不调用构造/析构(对 trivial 类型是内存填充级优化,但行为仍等价于循环赋值)。性能上无实质差别,std::ranges::fill 底层通常就转发给 std::fill 实现。
- 唯一实际区别是接口:前者更安全(类型检查更严)、更泛化(适配任意 range)、更少出错(避免
begin/end不匹配) - 对自定义 range(比如带哨兵的 view),
std::ranges::fill能正确处理,而std::fill会编译失败 - 不要指望它“更快”——它不是 SIMD 加速版;想批量初始化,还是得用
std::vector构造函数或assign()
容易被忽略的边界情况:空 range 和 const 容器
std::ranges::fill 对空 range 安全(比如空 std::vector 或长度为 0 的数组),什么也不做,不崩溃也不报错。但它**不能用于 const 容器**——这点和 std::fill 一样,本质是要求元素可赋值。
- 写
const std::vector<int> v(3); std::ranges::fill(v, 1);</int>→ 编译失败:无法将const int&绑定到int& - 写
std::vector<const int> v(3);</const>同样不行:元素类型本身不可赋值 - 对
std::array成员变量,若所在类是 const,也不能在 const 成员函数里调用std::ranges::fill
真正要“只读填充”,得换思路:用初始化列表、构造时填充,或者用 std::transform + 可变 lambda(但已不是 fill 场景了)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











