在 C++20 中, 头文件引入了一套强大的管道式、惰性求值的数据操作工具。相比传统的迭代器写法,它提供了更简洁的语法,更直观的链式组合,以及显著的可读性提升。下面通过一个完整的示例,演示如何利用 std::ranges::views 对一个整数序列进行筛选、变换、排序、去重,并最终将结果写入容器。
1. 准备数据
#include <vector>
#include <iostream>
#include <ranges>
#include <algorithm>
int main() {
std::vector <int> data{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
2. 定义操作链
auto processed = data
| std::ranges::views::filter([](int n){ return n % 2 == 0; }) // 取偶数
| std::ranges::views::transform([](int n){ return n * n; }) // 平方
| std::ranges::views::filter([](int n){ return n > 50; }) // 大于50
| std::ranges::views::unique(); // 去重
注意:
unique是一个 view,它在调用std::ranges::to或者通过std::ranges::for_each之类的终结操作时才会触发真正的去重工作。
3. 终结操作:复制到容器
std::vector <int> result;
std::ranges::to(result)(processed); // C++23 提供的简化语法
如果使用 C++20,终结操作可以写成
std::copy(processed.begin(), processed.end(), std::back_inserter(result));
4. 输出结果
std::cout << "处理结果: ";
for (int x : result) std::cout << x << ' ';
std::cout << '\n';
}
5. 运行效果
$ ./ranges_demo
处理结果: 64 100 144 196 256 324 400
- 解释:原始序列
[1..15]先筛选偶数得到[2,4,6,8,10,12,14];平方后[4,16,36,64,100,144,196];再筛选大于 50 的得到[64,100,144,196];最后去重(此处无重复)得到最终结果。
6. 进一步优化与技巧
- 组合视图:使用
std::ranges::views::all可以包装任何可遍历对象,保持兼容性。 - 链式管道:由于视图是惰性求值,整个链式操作在真正需要数据时才执行,避免不必要的拷贝。
- 自定义视图:通过
std::ranges::view_facade可以轻松创建自己的视图,例如滑动窗口、分组等。 - 性能考虑:在极大数据量下,避免在视图链中出现昂贵的临时对象;若需多次遍历,考虑先复制为容器。
7. 小结
C++20 的 `
` 与 “ 为现代 C++ 提供了一种声明式、惰性、链式的数据处理方式,既提升了代码可读性,又保持了高性能。熟练掌握视图组合,将使你的数据操作代码更简洁、更易维护。