## C++20:ranges 与 std::ranges::views 的全新视角

C++20 标准引入了 ranges 库,彻底改变了我们遍历容器和对序列进行操作的方式。之前,for 循环加上迭代器、std::transform、std::accumulate 等算法往往显得繁琐;现在,借助 std::ranges::views,可以用更短、更可读的表达式完成同样的工作。

1. 传统的循环写法

std::vector <int> nums{1, 2, 3, 4, 5};
std::vector <int> doubled;
for (int n : nums) {
    doubled.push_back(n * 2);
}

2. 使用 std::ranges::views::transform

#include <ranges>
#include <vector>

std::vector <int> nums{1, 2, 3, 4, 5};
auto doubled = nums | std::ranges::views::transform([](int n){ return n * 2; });

for (int d : doubled) {
    std::cout << d << ' ';
}

views::transform 并不立即执行,而是创建一个惰性视图,只有在遍历时才调用 lambda。这样可以避免不必要的拷贝。

3. 过滤与分区

如果我们只想保留偶数并乘以 3:

auto filtered = nums 
               | std::ranges::views::filter([](int n){ return n % 2 == 0; })
               | std::ranges::views::transform([](int n){ return n * 3; });

for (int v : filtered) std::cout << v << ' ';

输出 6 12

4. 组合多重视图

ranges 视图可以链式组合,像流水线一样。下面的例子演示对 1-100 的奇数进行平方并求和:

auto sum_of_squares = std::ranges::iota_view(1, 101)
    | std::ranges::views::filter([](int n){ return n % 2 == 1; })
    | std::ranges::views::transform([](int n){ return n * n; })
    | std::ranges::views::accumulate(0);

std::cout << sum_of_squares << '\n';

这比写一个 for 循环要简洁得多。

5. 视图 vs 算法

  • 视图 是惰性、无副作用的,适合链式操作。
  • 算法(如 std::transform)是立即执行的,常用于需要显式返回结果或副作用的场景。

在许多情况下,使用视图可以减少代码量并提高可读性。你可以把已有的 std::transformstd::for_each 等替换为对应的视图组合,尤其在需要多步处理时效果尤为明显。

6. 结语

C++20 的 ranges 为容器操作带来了更高层次的抽象,让代码更像自然语言。掌握 std::ranges::views,你会发现许多曾经繁琐的算法实现现在只需几行代码。欢迎尝试在自己的项目中逐步引入 ranges,感受代码的简洁与优雅。

发表评论