在 C++20 中,std::ranges 库为容器提供了一种更声明式、更表达式化的操作方式。相比传统的迭代器 + std::copy_if 或 std::remove_if,std::ranges 通过管道化操作实现了更简洁且易读的代码。本文将从基础语法、常用视图(view)以及性能考量四个方面,介绍如何在实际项目中利用 std::ranges 进行数据过滤。
1. 基础语法与示例
#include <iostream>
#include <vector>
#include <ranges>
#include <algorithm>
int main() {
std::vector <int> data{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto even_numbers = data | std::ranges::views::filter([](int n){ return n % 2 == 0; });
for (int n : even_numbers) {
std::cout << n << ' ';
}
// 输出: 2 4 6 8
}
- 管道符
|:将容器data连接到filter视图,形成一个新的可迭代范围。 views::filter:接收一个谓词(lambda 或函数),返回一个延迟评估的过滤视图。- 迭代器不必手动维护,只需按需遍历。
2. 常用视图(views)组合
std::ranges::views 提供了大量组合视图,常见的有:
| 视图 | 功能 | 示例 |
|---|---|---|
views::filter |
过滤元素 | view | views::filter(p) |
views::transform |
转换元素 | view | views::transform(f) |
views::take |
取前 N 个 | view | views::take(5) |
views::drop |
跳过前 N 个 | view | views::drop(3) |
views::reverse |
反转顺序 | view | views::reverse |
views::stride |
每隔 N 个 | view | views::stride(2) |
views::join |
合并嵌套容器 | view_of_views | views::join |
组合示例:取前 5 个偶数并平方
auto result = data
| std::ranges::views::filter([](int n){ return n % 2 == 0; })
| std::ranges::views::take(5)
| std::ranges::views::transform([](int n){ return n * n; });
for (int x : result) std::cout << x << ' '; // 输出: 4 16 36 64 100
3. 与 STL 算法兼容
std::ranges 视图可以直接与标准算法一起使用,且能享受视图的延迟求值特性。
auto sum = std::accumulate(
data | std::ranges::views::filter([](int n){ return n > 5; }),
0
);
注意:某些算法(如 std::sort)需要可修改的范围,需使用 std::ranges::subrange 或 std::ranges::iota_view 等。
4. 性能考量
-
延迟求值
视图在迭代时按需执行过滤/转换,避免一次性生成临时容器,降低内存占用。 -
小对象
视图是“轻量级”对象,通常只包含迭代器或函数对象,复制开销极小。 -
缓存友好
由于不产生新容器,缓存命中率更高。
但若视图链很长,可能会导致多层函数调用;可使用std::ranges::views::common将范围转为常规迭代器以减少层级。 -
并行执行
C++20 为std::ranges::views加入了std::execution支持,可通过std::ranges::copy等函数并行化:std::vector <int> out(data.size()); std::ranges::copy( data | std::ranges::views::filter([](int n){ return n % 2 == 0; }), std::execution::par, std::begin(out) );
5. 典型应用场景
-
日志过滤
在高频日志系统中,仅保留指定级别的日志条目,避免存储与 I/O 负载。 -
网络包处理
对入站数据包进行速率限制、内容检查等。 -
大数据预处理
对 CSV、JSON 等文件中大量行进行筛选与转换后,再交给机器学习模块。
6. 小结
std::ranges提供了声明式、链式的数据操作方式。- 通过
views::filter、views::transform等组合,可实现复杂的数据流,代码简洁且易维护。 - 延迟求值与轻量级对象使其在性能上优于传统迭代器+算法的做法。
- 结合并行执行,可进一步提升吞吐量。
建议在新项目中使用 C++20 的 std::ranges 进行数据过滤与转换,以提升代码质量与运行效率。祝你编码愉快!