如何在 C++20 中使用 std::ranges 对容器进行筛选和变换?

在 C++20 里,std::ranges 为容器操作带来了极大的便利,让代码既简洁又易读。下面通过一个完整的例子,演示如何利用 std::ranges::filter, std::ranges::transform, std::ranges::to 等工具,对 std::vector<int> 进行筛选、变换,并最终得到结果容器。

#include <iostream>
#include <vector>
#include <ranges>
#include <algorithm>

int main() {
    // 原始数据
    std::vector <int> data{1, 2, 3, 4, 5, 6, 7, 8};

    // 1. 先筛选出偶数
    auto even_filter = std::ranges::views::filter([](int n){ return n % 2 == 0; });

    // 2. 对偶数进行平方
    auto square_transform = std::ranges::views::transform([](int n){ return n * n; });

    // 3. 组合视图
    auto processed = data | even_filter | square_transform;

    // 4. 收集结果到 vector
    std::vector <int> result;
    result = processed | std::ranges::to<std::vector>();

    // 打印结果
    std::cout << "偶数的平方: ";
    for (auto v : result)
        std::cout << v << ' ';
    std::cout << '\n';

    return 0;
}

关键点说明

  1. views::filter
    接收一个谓词,返回一个延迟求值的视图。只有当你遍历视图时,才会真正调用谓词,极大节省了中间容器的创建。

  2. views::transform
    类似于 std::transform,但返回的是一个视图,支持链式组合。这里用它来计算平方。

  3. 管道操作符 (|)
    C++20 为容器视图提供了管道语法,使得链式调用更像 DSL,代码更直观。

  4. ranges::to
    用来把视图“收集”到目标容器。std::ranges::to<std::vector>() 会创建并返回一个 std::vector,内容为视图中的元素。

性能优势

  • 无中间临时容器filtertransform 组合后,元素在一次遍历中完成筛选与变换,无需为中间结果创建额外容器。
  • 按需求值:视图是惰性的,只有真正需要访问元素时才会触发计算。
  • 可组合性:视图可以无缝组合成更复杂的处理链,代码易于维护。

小结

C++20 的 std::ranges 为容器操作提供了一种更接近函数式编程的方式。通过视图组合、惰性求值与直观的管道语法,你可以轻松实现复杂的数据处理逻辑,同时保持代码简洁、可读且高效。希望本文能帮助你快速上手 std::ranges,并在实际项目中发挥其优势。

发表评论