C++20范围库是底层抽象范式升级,以range统一容器、迭代器与算法,支持惰性求值、组合式视图(如filter/transform)和简化for循环及算法调用。

C++20 的范围库(Ranges)不是“增强版 STL”,而是一次底层抽象范式的升级:它把“容器 + 迭代器 + 算法”三件套,统一成更自然、更组合化、更惰性求值的 范围(range) 概念。你不再需要手动传 begin()/end(),也不必担心迭代器失效或类型不匹配——for 循环和标准算法从此变得更像 Python 的 for item in list 或 Rust 的 iter().filter().map()。
什么是 range?不只是容器的别名
一个 range 是任何能通过 begin() 和 end() 获得一对迭代器的对象(比如 vector、array、string),但关键在于:C++20 把这个概念正式纳入标准,并提供了统一接口和配套工具。它不等于容器,而是更高一层的抽象——比如子串视图(std::views::subrange)、过滤后视图(std::views::filter)、转换后视图(std::views::transform)都是 range,但它们本身不拥有数据,也不立即计算结果。
- range 可以是 owning(如 vector)或 view(轻量、无拥有权、惰性)
- view 是 range 的子集,要求常数时间构造/拷贝/移动,且不持有元素副本
- 所有标准算法(如 sort、find、count)现在都有 range 版本(如 std::ranges::sort),直接接受 range,无需迭代器对
告别 begin/end:for 循环彻底简化
以前写循环要记住配对、类型一致、避免越界;现在只要对象是 range,就能直接用基于范围的 for:
std::vectorv = {1, 2, 3, 4, 5}; // 传统写法(冗余且易错) for (auto it = v.begin(); it != v.end(); ++it) { /* ... */ } // C++20 写法(干净、安全、可读) for (int x : v) { / 直接用元素 / }
// 更进一步:直接遍历处理后的逻辑视图 for (int x : v | std::views::filter([](int n){ return n % 2 == 0; }) | std::views::transform([](int n){ return n * n; })) { std::cout << x << ' '; // 输出 4 16(偶数的平方) }
注意:| 是管道操作符(由 operator| 重载支持),让视图组合像 Unix 命令一样直观。整个链式表达式仍是 view,不会分配新容器,也不会立刻执行——直到你遍历它。
立即学习“C++免费学习笔记(深入)”;
算法变“懒”了:std::ranges::xxx vs std::xxx
C++20 提供两套并行算法:老式 std::xxx(仍可用)和新式 std::ranges::xxx。后者有三大变化:
- 参数变简单:直接接收 range,自动提取 begin/end
- 约束更严格:编译期检查 range 是否满足算法要求(如 sort 要求 random_access_range + sortable)
- 返回类型更合理:例如
std::ranges::find返回iterator,而std::ranges::find_if也一样,不再有“返回 bool + out-param”的混乱设计
示例对比:
// C++17 及之前
auto it = std::find(v.begin(), v.end(), 42);
if (it != v.end()) { /* found */ }
// C++20
if (auto res = std::ranges::find(v, 42); res != v.end()) { / found / }
// 或更惯用:
if (std::ranges::find(v, 42) != v.end()) { ... }
常用 views 实战:filter、transform、take、drop、join
标准库提供了一组开箱即用的 view 适配器(定义在 中),它们是构建数据流水线的核心积木:
std::views::filter(pred):只保留满足谓词的元素(惰性,不复制)std::views::transform(fn):对每个元素应用函数,生成新 view(不执行,仅描述)std::views::take(n):取前 n 个;std::views::drop(n):跳过前 n 个std::views::join:把 range of ranges(如 vector>)展平为单层 range std::views::iota(start, end):生成 [start, end) 区间整数序列(类似 Python 的 range())
组合示例:
auto nums = std::views::iota(1, 100)
| std::views::filter([](int x){ return x % 3 == 0 || x % 5 == 0; })
| std::views::take(10);
for (int x : nums) {
std::cout << x << ' '; // 输出前 10 个 3 或 5 的倍数:3 5 6 9 10 12 15 18 20 21
}
这段代码没有创建任何中间 vector,全程零堆分配,语义清晰,且可在编译期部分优化。
Ranges 不是语法糖,它是 C++ 向声明式、组合式、安全高效编程迈出的关键一步。它让算法更易读、更难写错、更容易复用。你不需要立刻重写全部代码,但从下一个新函数开始,试着用 std::ranges:: 和 | std::views::,你会很快感受到那种“本该如此”的流畅感。











