std::fill_n与std::ranges::fill_n的实用差异是什么?
std::fill_n 与 std::ranges::fill_n 的实用差异
虽然两者核心功能都是填充指定数量的元素,但C++20引入的std::ranges::fill_n在易用性、安全性和灵活性上比传统std::fill_n有明显提升,具体差异如下:
1. 调用方式更简洁,无需手动传递迭代器
传统std::fill_n要求手动传入起始迭代器和计数,而std::ranges::fill_n可直接接受容器、数组、视图等完整范围,自动处理迭代器逻辑:
#include <vector> #include <algorithm> #include <ranges> int main() { std::vector<int> v(10); // std::fill_n 需手动传起始迭代器 std::fill_n(v.begin(), 5, 42); // std::ranges::fill_n 直接传容器,语义更直观 std::ranges::fill_n(v, 5, 0); }
2. 编译期类型安全(基于Concepts约束)
std::ranges::fill_n利用C++20的**概念(Concepts)**做编译期检查,确保传入的范围是可写的(std::ranges::writable)。如果尝试传入只读范围(比如const容器),编译器会直接报错;而传统std::fill_n只会在运行时产生未定义行为:
#include <vector> #include <algorithm> #include <ranges> int main() { const std::vector<int> cv(10); // 编译报错:违反writable概念约束 // std::ranges::fill_n(cv, 5, 42); // 编译通过,但运行时是未定义行为(写入只读内存) // std::fill_n(cv.begin(), 5, 42); }
3. 返回值采用结构化结果,可读性更强
传统std::fill_n返回最后一个被填充元素的下一个迭代器;而std::ranges::fill_n返回std::ranges::fill_n_result结构体,其中in成员指向该位置。结构化返回在复杂场景下更易读,也支持解构使用:
#include <vector> #include <algorithm> #include <ranges> #include <iostream> int main() { std::vector<int> v(10); // std::fill_n 返回迭代器 auto it = std::fill_n(v.begin(), 5, 42); std::cout << "下一个位置索引: " << std::distance(v.begin(), it) << "\n"; // 输出5 // std::ranges::fill_n 返回结构化结果 auto result = std::ranges::fill_n(v, 5, 0); std::cout << "下一个位置索引: " << std::distance(v.begin(), result.in) << "\n"; // 输出5 }
4. 天然支持范围视图(Views)
std::ranges::fill_n可直接与C++20范围视图配合使用,无需额外转换迭代器,代码更连贯:
#include <vector> #include <ranges> #include <algorithm> int main() { std::vector<int> v(10); // 对容器前5个元素的视图,填充前3个为99 std::ranges::fill_n(std::views::take(v, 5), 3, 99); // 此时v[0]-v[2]为99,v[3]-v[4]保持初始值0 }
传统std::fill_n要实现同样效果,需先将视图转换为迭代器,代码更繁琐:
// 等价的std::fill_n写法 auto view = std::views::take(v, 5); std::fill_n(view.begin(), 3, 99);
5. 对自定义范围的适配性更强
std::ranges::fill_n支持所有符合std::ranges::output_range概念的自定义范围类型,无需手动编写迭代器适配代码;而传统std::fill_n仅接受标准迭代器,自定义类型需额外实现迭代器接口才能兼容。
内容的提问来源于stack exchange,提问作者Hesky Fisher
相关产品推荐
相关产品推荐

