1. 理解std::ranges视图的本质
C++20引入的std::ranges视图(views)不是数据的容器,而是对现有序列的轻量级包装。它们遵循"惰性求值"原则——只有在真正需要数据时才会执行计算。这种设计带来了显著的性能优势,特别是在处理大型数据集时。
视图的核心特征包括:
- 零拷贝:视图本身不存储数据,只是引用底层序列
- 组合性:多个视图可以管道式组合(|操作符)
- 惰性计算:操作会延迟到元素被访问时才执行
cpp复制#include <ranges>
#include <vector>
#include <iostream>
int main() {
std::vector nums{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 创建过滤和转换视图
auto view = nums | std::views::filter([](int n) { return n % 2 == 0; })
| std::views::transform([](int n) { return n * 2; });
for (int n : view) {
std::cout << n << " "; // 输出: 4 8 12 16 20
}
}
2. 常用视图类型及其应用场景
2.1 基础视图操作
filter视图是最常用的过滤工具。它接受一个谓词函数,只保留满足条件的元素。在实际项目中,我经常用它来替代传统的手写循环过滤:
cpp复制std::vector<Product> products = getProducts();
auto expensive = products | std::views::filter([](const Product& p) {
return p.price > 1000;
});
transform视图则用于元素转换。相比传统循环,它能更清晰地表达意图:
cpp复制// 传统方式
std::vector<std::string> names;
for (const auto& user : users) {
names.push_back(user.name);
}
// ranges方式
auto names = users | std::views::transform([](const User& u) { return u.name; });
2.2 高级视图组合
take/drop视图处理序列的子集特别有用。在分页处理时,我经常这样组合它们:
cpp复制// 获取第2页的数据(每页10条)
auto page2 = data | std::views::drop(10) | std::views::take(10);
join视图可以扁平化嵌套结构。处理树形数据时,它能大幅简化代码:
cpp复制std::vector<std::vector<int>> matrix = {{1,2}, {3,4,5}, {6}};
auto flat
