C++20新特性_范围 (Ranges)

文章目录

  • [第一章 C++20核心语法特性](#第一章 C++20核心语法特性)

本文记录C++20新特性之范围 (Ranges)。

第一章 C++20核心语法特性

1.2 范围 (Ranges)

C++20引入了范围Range库,这是自C++11以来最大的一次现代化升级,可以让代码书写更简介,更符合现代化风格。

下面是C++11中容器的遍历方式,特点是传入两个迭代器,begin()和end().

cpp 复制代码
std::vector<int> v = {3, 1, 4};
std::sort(v.begin(), v.end()); // 必须写两次 v

在C++20中,实现上面的功能,使用了更简洁的方式。

1.2.1 Ranges定义

Ranges库包含在头文件 中,主要有以下几个概念。
范围(Ranges) : 任何可以提供begin() 和 end() 的东西都是Range, 例如,vector,std::array,C风格数组等。范围的引入让STL库中的算法更简洁,C++11给STL库传递开始和结束的迭代器,使用ranges只需要传递容器名称即可。
视图(View) : 视图是Ranges的精髓,视图主要的特点总结如下:

特点1:不拥有数据。可以把视图看成是指向原始数据的容器,类似于一个"智能指针",只是指向而不拥有,所以原始数据的生命周期结束,视图也会结束。

特点2:惰性求值。 这是视图最强大特性,操作多个视图时,不会立即执行计算,而是使用时才进行计算。

特点3:可组合。多个使用可以通过 管道符"|"进行组合。

**视图适配器:**用于生成View的工具,常用的视图适配器如下:

  • filter(pred) 筛选出满足谓词 pred 的元素。
  • transform(fn) 对每个元素应用函数 fn,并产生结果。
  • take(n) 获取范围中的前 n 个元素。
  • drop(n) 跳过范围中的前 n 个元素。
  • reverse 反转范围中元素的顺序。
  • keys 对于 map 或类似的关联容器,只获取键 (key)。
  • values 对于 map 或类似的关联容器,只获取值 (value)。
  • elements 对于元组 (tuple) 或 pair 的范围,只获取第 N 个元素。
  • iota(start, end) 生成一个从 start 到 end(不含)的数字序列。
  • join 将一个"范围的范围"扁平化为一个单一的范围。

1.2.2 使用说明

示例1:简化算法调用

下面例子可以明显看出,之前使用了迭代器方式进行遍历,现在直接传递容器即可。

cpp 复制代码
    void test()
    {
		std::vector<int> vec = { 1,2,3,4,5 };
        // C++11 的遍历方式
        std::for_each(vec.begin(), vec.end(), 
            [](int& n) {
            n *= 2;
            cout << n << " ";
         });
        cout << endl;
        // 2 4 6 8 10
        
        // C++20遍历方式
        std::ranges::for_each(vec, [](int& n) {
            n *= 2;
            cout << n << " ";
		});
        cout << endl;
		// 4 8 12 16 20
    }
示例2: 管道操作与试图组合

假设,对现在的数据过滤出偶数,取出前3个偶数后,进行反转。

cpp 复制代码
void test2()
 {
		std::vector<int> data = { 10,2,3,6,5,4,7,8,9,11 };

     // 过滤出偶数
     auto result1 = data 
| std::views::filter([](int n) { return n % 2 == 0; }); // 过滤偶数
     // C++20遍历方式
     std::ranges::for_each(result1, [](int& n) {
         cout << n << " ";
         });
     cout << endl;
     // 10 2 6 4 8

     // 使用管道符 操作
     auto result = data 
         | std::views::filter([](int n) { return n % 2 == 0; }) // 过滤偶数
| std::views::take(3) // 取前3个
| std::views::reverse; // 反转顺序

     // C++20遍历方式
     std::ranges::for_each(result, [](int& n) {
         cout << n << " ";
     });
     cout << endl;
     // 6 2 10
 }

总结:std::views::filter 传递一个 lambda表达式

示例3:过滤并修改map

下面例子展示了在map容器中使用视图适配器。

cpp 复制代码
void test()
 {
     std::map<std::string, int> scores = {
          {"Alice", 85}, {"Bob", 59}, {"Charlie", 92}, {"Dave", 40}
     };

     std::cout << "Passing students:\n";

     // 遍历 map,过滤分数 >= 60 的学生,并只获取他们的名字 (key)
     auto passers = scores
         | std::views::filter([](const auto& pair) { return pair.second >= 60; })
         | std::views::keys; // 专门用于 map 的视图,只取 key

     for (const auto& name : passers) {
         std::cout << "- " << name << "\n";
     }
 }
相关推荐
啟明起鸣2 天前
【C++20新特性】概念约束特性与 “模板线程池”,概念约束是为了 “把握未知对象”
开发语言·c++·c++20·模板线程池
linweidong3 天前
虎牙C++面试题及参考答案(上)
stl·vector·线程·内存管理·c++20·c++面试·c++调用
吐泡泡_4 天前
C++20(概念和约束)
c++20
訫悦7 天前
体验在Qt中简单使用C++20的协程
qt·c++20·协程
fpcc11 天前
C++20中的预处理器宏——__VA_OPT__
c++20
Codeking__13 天前
C++20的consteval和constinit(接C++11的constexpr)
算法·c++20
六bring个六16 天前
C++20协程
c++20·协程
C++实习生16 天前
Visual C++ 2005 Express 中文版
express·c++20
Ethan Wilson18 天前
VS2019 C++20 模块相关 C1001: 内部编译器错误
开发语言·c++·c++20
DYS_房东的猫18 天前
《 C++ 零基础入门教程》第10章:C++20 核心特性 —— 编写更现代、更优雅的 C++
java·c++·c++20