LiSheng's blog LiSheng's blog
首页
笔记
个人简历
随笔集
GitHub (opens new window)
首页
笔记
个人简历
随笔集
GitHub (opens new window)
  • golang

  • cplus

    • 内存相关

    • 面向对象

    • STL相关

    • 内置数据结构
    • 数据结构示例
    • go和c++对比
    • 关键字

      • static
      • const、volatile、mutable
      • const_cast、dynamic_cast
      • struct、class、union
      • new、delete
      • operator
      • c++20 range
    • leetcode

    • 存储技术

    • 分布式系统

    • 计算机网络

    • Linux操作系统

    • Redis

    • 其他

    • 笔记
    • cplus
    • 关键字
    lisheng
    2024-09-10
    目录

    c++20 range

    C++20引入了Ranges库,这是对传统STL算法和迭代器的一大扩展,提供了更灵活、更现代的方式来处理序列数据。Ranges引入了几个关键的概念和组件,包括范围、视图、适配器和新的算法,这些都为C++程序员在数据处理方面带来了更多便利。

    # Ranges的核心特性

    # 1. 范围 (Ranges)

    范围是一种抽象,代表了一个连续的、可迭代的元素序列。与传统的迭代器配对不同,范围通过单一的对象表示一个序列的开始和结束。这简化了很多算法的使用方式,因为你不再需要传递两个迭代器来指定一个序列的开始和结束,而只需要传递一个范围对象。

    # 2. 视图 (Views)

    视图是对一个范围的引用,提供了一种无需复制底层数据的方式来访问或修改数据。视图是懒加载的,它们不执行任何操作直到被遍历或在某种方式上被使用。这使得它们非常高效,尤其是在管道或链式操作中。常见的视图包括filter, transform, reverse, take, drop等。

    # 3. 适配器 (Adapters)

    适配器是特殊类型的视图,用于变换数据。例如,std::views::transform 可以将一个函数应用于范围内的每个元素,而 std::views::take 可以产生一个新的视图,仅包含原范围的前N个元素。

    # 4. 新的算法

    Ranges为许多传统的STL算法提供了替代品,这些算法可以直接操作范围对象。这些算法包括但不限于ranges::sort, ranges::find, ranges::copy等,它们都可以接受一个范围作为输入,使得代码更加直观和简洁。

    # 使用场景

    # 1. 数据处理和转换

    当需要对数据集进行过滤、转换或任何形式的处理时,Ranges提供的视图和适配器可以非常方便地使用。例如,可以轻松地链式调用多个操作,而不会产生中间的临时容器。

    auto result = data | std::views::filter(is_odd) | std::views::transform(square);
    
    1

    # 2. 复杂的查询表达式

    对于需要从数据中构建复杂查询的场景,如从集合中提取满足特定条件的元素,Ranges使得表达这种查询变得非常简洁。

    auto subset = data | std::views::filter([](const auto& item) { return item.isActive && item.value > 10; });
    
    1

    # 3. 性能敏感的场合

    由于视图是懒加载的,它们可以用来提高性能,尤其是在处理大量数据或在只需要序列的一部分时。这可以避免不必要的数据复制和提前计算。

    # 4. 与现代C++代码的集成

    Ranges使得代码更现代化,易于维护和理解。它与现代C++的其他特性如智能指针、lambda表达式和并发API很好地集成在一起。

    下面是几个使用 C++20 Ranges 的例子,展示如何在实际应用中使用它们来简化代码并提高表达力。这些示例覆盖了常见的数据处理任务,如过滤、转换和排序等。

    # 示例 1: 过滤和转换

    假设我们有一个整数数组,我们想要提取其中的偶数,并将它们每个都乘以2。使用 C++20 Ranges,我们可以很容易地实现这一点。

    #include <iostream>
    #include <vector>
    #include <ranges>
    
    int main() {
        std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
        // 使用 std::views::filter 和 std::views::transform
        auto even_numbers_transformed = numbers 
                                        | std::views::filter([](int n) { return n % 2 == 0; })
                                        | std::views::transform([](int n) { return n * 2; });
    
        // 输出结果
        for (int n : even_numbers_transformed) {
            std::cout << n << " ";
        }
        std::cout << std::endl;
    
        return 0;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    # 示例 2: 串联多个视图

    我们可以将多个视图串联起来处理字符串列表,例如,选取特定条件的字符串后,再转换它们的格式。

    #include <iostream>
    #include <string>
    #include <vector>
    #include <ranges>
    
    int main() {
        std::vector<std::string> names = {"Alice", "Bob", "Charlie", "David"};
    
        // 过滤出长度大于3的名字,并转换为大写
        auto long_names_upper = names
                                | std::views::filter([](const std::string& name) { return name.size() > 3; })
                                | std::views::transform([](const std::string& name) {
                                    std::string upper_case;
                                    std::ranges::transform(name, std::back_inserter(upper_case), ::toupper);
                                    return upper_case;
                                });
    
        // 输出结果
        for (const auto& name : long_names_upper) {
            std::cout << name << " ";
        }
        std::cout << std::endl;
    
        return 0;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

    # 示例 3: 使用 Ranges 排序和去重

    我们也可以使用 Ranges 对数据进行排序和去重。

    #include <iostream>
    #include <vector>
    #include <ranges>
    
    int main() {
        std::vector<int> nums = {4, 1, 3, 4, 2, 1, 3};
    
        // 排序并去重
        auto unique_sorted = nums 
                             | std::views::sort // 排序
                             | std::views::unique; // 去重
    
        // 输出结果
        for (int n : unique_sorted) {
            std::cout << n << " ";
        }
        std::cout << std::endl;
    
        return 0;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    # 注意事项

    • 在使用 std::views::sort 和其他需要修改数据的视图时,需要确保容器本身是可修改的。
    • Ranges 库中的一些视图如 sort 和 unique 需要在内部进行数据的修改,因此不能直接应用于 const 容器或视图。

    通过这些例子,我们可以看到 C++20 Ranges 提供了强大的工具,使得数据处理更加灵活和直观。

    编辑 (opens new window)
    上次更新: 2024/09/13, 11:59:12
    operator
    排序算法

    ← operator 排序算法→

    最近更新
    01
    ceph分布式存储-对象存储(RGW)搭建
    10-27
    02
    ceph分布式存储-集群客户端连接
    10-27
    03
    ceph分布式存储-管理crushmap
    10-27
    更多文章>
    Theme by Vdoing
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式