std::ranges是C++20对标准算法的现代化重设计,提供范围重载、惰性视图和概念约束;支持直接传容器、链式视图组合(如filter|transform)、零拷贝计算,并要求C++20编译支持。

std::ranges 是 C++20 引入的核心新特性之一,它把算法、迭代器和容器的交互方式彻底重构为更安全、更组合化、更易读的形式。它不是“另一个算法库”,而是对 的现代化重设计——所有标准算法现在都有了范围(range)重载,支持直接传入容器或视图,无需手动写 begin()/end();同时引入了惰性求值的 views(视图),可链式组合、零拷贝、不产生中间容器。
ranges 算法:告别 begin/end,直接操作容器
传统写法要显式传入迭代器对:
std::vector v = {1, 2, 3, 4, 5};std::sort(v.begin(), v.end(), std::greater{});
ranges 版本直接传容器或任意 range:
std::ranges::sort(v, std::greater{}); // ✅ 自动推导 begin/endstd::ranges::reverse(v); // ✅ 更简洁std::ranges::find(v, 3); // 返回的是 iterator,但类型更精确(sized_iterator 等)
关键点:
立即学习“C++免费学习笔记(深入)”;
所有 std::algorithm 中的算法在 std::ranges 命名空间下都有对应重载;支持任何满足 range 概念的对象(包括数组、vector、string、initializer_list,甚至 C 风格字符串指针 + 长度);多数算法返回 std::ranges::subrange 或更语义化的迭代器类型,配合结构化绑定更清晰;部分算法有“稳定”、“投影”等增强重载,比如 std::ranges::sort(v, {}, &Person::age)。
views:惰性、可组合、零分配的视图管道
views 不是容器,也不保存数据,只是“描述如何查看数据”的轻量对象。创建开销极小,组合时不做实际计算,直到你遍历它。
最常用的方式是用管道操作符 | 链式调用:
auto even_squares = v | std::views::filter([](int x) { return x % 2 == 0; }) | std::views::transform([](int x) { return x * x; });// 此时 nothing is computedfor (int x : even_squares) { /* 4, 16 */ } // ✅ 此时才逐个计算
常用内置 views:
std::views::filter(pred):筛选满足条件的元素;std::views::transform(fn):对每个元素做映射;std::views::take(n) / std::views::drop(n):取前 n 个 / 跳过前 n 个;std::views::join:展平嵌套 range(如 vector>);std::views::iota(start, end):生成整数序列(类似 Python 的 range);std::views::keys / std::views::values:提取 map 的键或值。
注意:views 是 const-friendly 且可复制的;多次遍历同一 view 可能触发重复计算(除非底层 range 支持随机访问且 view 是纯函数式)。
range 概念与自定义 range 入门
C++20 用 concept 精确定义了什么是 range:
std::ranges::range:T 有 begin() 和 end(),返回兼容的迭代器;std::ranges::view:range + 移动代价为 O(1)(即轻量);std::ranges::sized_range:支持 size() 且为 O(1);std::ranges::random_access_range:支持 operator[] 和随机跳转。
你可以轻松让自定义类型支持 ranges:
struct IntRange { int from_, to_; struct iter { int val; int operator*() const { return val; } iter& operator++() { ++val; return *this; } bool operator!=(const iter& other) const { return val != other.val; } }; iter begin() const { return {from_}; } iter end() const { return {to_}; }};// 现在可以直接用:for (int x : IntRange{0, 3}) { ... }// 也能参与 views:IntRange{0,10} | views::filter(...);
实用建议与避坑提示
刚上手容易踩的几个点:
别混用老式迭代器和 ranges 算法:例如 std::ranges::sort(it1, it2) 是错的,必须传 range;views 默认不可存储(尤其 lambda 捕获):若需保存,用 auto 或显式模板(std::ranges::filter_view 等);某些 views(如 filter)不满足 sized_range,调 size() 会编译失败;调试时无法直接打印 view —— 它不是容器,需转成 vector 或用 range-for 查看;编译需开启 C++20(-std=c++20),GCC 10+/Clang 13+/MSVC 19.30+ 支持较完整。
基本上就这些。ranges 不是炫技,而是让 C++ 容器操作回归“所见即所得”:写得像描述逻辑,运行得像手工优化。从今天起,少写 begin/end,多用 | 管道,你会慢慢觉得以前的写法有点笨重。
以上就是c++++20 Ranges库入门教程_c++ std::ranges用法与视图详解【新特性】的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1488866.html
微信扫一扫
支付宝扫一扫