首页 > 编程语言 >C++系列十:日常学习-范围库Ranges

C++系列十:日常学习-范围库Ranges

时间:2023-10-09 20:26:58浏览次数:41  
标签:std views C++ auto 视图 Ranges 日常 numbers

目录

前言

不错麽

内容参考

  1. https://zh.cppreference.com/w/cpp/ranges
  2. Chatjpt

总结注意点:

  1. 确保你的C++编译器支持C++20标准
  2. 包含 ranges 头文件
  3. views的操作是惰性的,它们不会立即执行,而是在需要时计算。这意味着你可以构建复杂的管道,而不必担心性能问题。提供性能优势,因为它们避免了不必要的数据拷贝和临时存储。在处理大型数据集时,这种优化尤为重要。
  4. 使用views不会修改原始数据,它们只是提供了对数据的查看和操作方式。因此,原始数据保持不变,不会被修改。
  5. 要小心处理可能的异常情况,例如范围越界或无效的操作。可以使用try-catch块来处理异常。
  6. 管道操作符 |(竖线符号)=>数据处理操作可以从左到右依次执行,

介绍

C++20引入了Ranges库,其中的views是该库的一个关键组成部分。views提供了一种现代化的、功能强大的方法来处理数据序列,它基于"range-based"编程范式,允许你以声明性的方式对数据序列进行操作,而无需手动编写循环。以下是关于views的详细介绍:

  1. 什么是views

    views是C++20中Ranges库的一部分,它代表了一个数据序列的虚拟视图。这个视图允许你以一种便捷和现代的方式访问和操作数据,同时不需要实际地拷贝或修改原始数据。views的操作是惰性的,只有在需要的时候才会执行。

  2. 视图的创建:

    你可以通过调用标准容器的views成员函数或使用适配器来创建视图。例如,可以使用std::vector创建一个视图:

    std::vector<int> numbers = {1, 2, 3, 4, 5};
    auto view = numbers | std::views::transform([](int x) { return x * 2; });
    

    在这里,std::views::transform是一个视图适配器,它将一个函数应用于容器中的每个元素,创建一个新的视图。

  3. 视图的操作:

    一旦创建了视图,你可以对其执行各种操作,这些操作包括但不限于:

    • 筛选(filtering):筛选出满足特定条件的元素。

    • 映射(mapping):将函数应用于序列中的每个元素。

    • 切片(slicing):选择范围内的元素。

    • 排序(sorting):对元素进行排序。

    你可以将多个操作组合在一起来创建复杂的数据处理管道,而这些操作都是惰性执行的。

  4. 遍历视图:

    一旦创建了视图,你可以使用for循环或范围for循环来遍历它。视图会在遍历时动态计算元素,而不会一次性生成所有元素。

    for (int num : view) {       std::cout << num << " ";   }
    
  5. 性能优势:

    views具有优化的性能。它们避免了不必要的数据拷贝和临时存储,使得在处理大型数据集时非常高效。

  6. 自定义视图:

    你还可以创建自定义的视图,通过实现必要的迭代器和操作符来定义你自己的数据序列操作。

  7. views的应用场景:

    views适用于各种应用场景,包括数据转换、筛选、数据流处理、映射、集合操作等。它们可以使你的代码更加清晰、可读和高效。

总之,views是C++20引入的一个重要特性,它使得序列处理变得更加简单和现代化。它们提供了一种优雅的方式来处理数据序列,避免了繁琐的手动迭代和数据操作。在使用时,请确保你的编译器支持C++20标准并了解如何正确使用Ranges库以发挥其强大的功能。

举例:

std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用views::transform将每个元素翻倍=>2 4 6 8 10
auto doubled = numbers | std::views::transform([](int x) { return x * 2; });
// 使用views::filter筛选偶数 =>2 4
auto evenNumbers = numbers | std::views::filter([](int x) { return x % 2 == 0; });
// 使用views::slice选择范围[1, 3)=> 2 3 4
auto slicedRange = numbers | std::views::slice(1, 4);
// 链式操作:筛选偶数,然后翻倍=>4 8
auto result = numbers | std::views::filter([](int x) { return x % 2 == 0; })
                      | std::views::transform([](int x) { return x * 2; });
// 使用views::iota生成范围[1, 10)=>1~9
auto sequence = std::views::iota(1, 10);
// 生成无限递增序列~~~
auto infiniteSequence = std::views::iota(1);   
// 使用views::reverse反向迭代容器=>5 4 3 2 1
auto reversed = numbers | std::views::reverse;    
// 使用views::concat合并两个容器
std::vector<int> numbers1 = {1, 2, 3};
std::vector<int> numbers2 = {4, 5, 6};
auto combined = std::views::concat(numbers1, numbers2);
for (int num : doubled) {
  std::cout << num << " "; 
//拆分字符串
std::string text = "Hello,World,C++,Ranges";
auto splitView = text | std::views::split(',');
for (const auto& range : splitView) {
    std::string token(range.begin(), range.end());
    std::cout << token << std::endl;
} 

//对比:
auto const ints = {0,1,2,3,4,5};
auto even = [](int i) { return 0 == i % 2; };
auto square = [](int i) { return i * i; };
// 组合视图的“管道”语法:
for (int i : ints | std::views::filter(even) | std::views::transform(square)) {
    std::cout << i << ' ';
}
std::cout << '\n';
// 传统的“函数式”组合语法:
for (int i : std::views::transform(std::views::filter(ints, even), square)) {
    std::cout << i << ' ';
}


还有许多适配器就不一一举例说明了。
高深的就不探究了,会使用好工具就得了。

标签:std,views,C++,auto,视图,Ranges,日常,numbers
From: https://www.cnblogs.com/zhouyitty/p/17753039.html

相关文章

  • c++ OOP(2)
    目录运算符重载继承多态抽象基类运算符重载重新定义+-*/操作,对同类对象使用,以时间类Time为例子进行理解Time.hclassTime{private:inthour,minute;public:Time();Time(inth,intm);voidshow_time();Timeoperato......
  • 如何在visual c++ 6.0中显示行号
    1.下载VC6LineNumberAddin组件,地址:https://pan.baidu.com/s/1rVHL7nQ3Ij0sDkOVUWL_GA下载完后解压后,会有如下3个文件 2.如果你的VC安装在C盘,请拷贝文件VC6LineNumberAddin.dll到安装目录:C:\VC++\MicrosoftVisualStudio\Common\MSDev98\AddIns3.注册双击VC6LineNum......
  • 有效解决VC++6.0一个工程不能有多个main函数的解决方案
    对于初学者来说,需要做很多练习,就需要创建多个main()函数,但C语言只能有一个main()函数,那么通常的做法就是:【方法一】:讲其他文件中的main()函数注释掉,但该方法比较费时费力,不推荐【方法二】:在VC++6.0中,在工程左边fileview里工程下的sourcefiles中,选中前一个带main函数的文件, ......
  • Microsoft Visual C++ 14.0 or greater is required.
    MicrosoftVisualC++14.0orgreaterisrequired.表示缺少VisualStudio2015及以上版本可以通过以下途径解决。最好是第二、三种途径。 一、直接下载对应版本的.whl文件,然后运行pipinstallxxx.whl 二、按照提示去官网下载VisualStudio2015及以上版本都可以,必须安装C++......
  • Visual Studio Code配置C/C++开发环境
    C/C++开发中的IDE非常多,网上有推荐安装VisualStudio2019/2020/2022。但是登录官方网址下载,此软件体积非常大(8G以上),且企业版、专业版会收费。因此,我们推荐大家可以尝试通过VisualStudioCode来配置C/C++开发环境环境准备MinGW-W64,此环境是编译C、C++的源码【必安装】CMake,......
  • C++ 模板特化
    模板特化介绍模板特化是指在模板的基础上,针对某些特定的值,提供一种特殊的实现方式,模板特化分为两种,类模板特化和函数模板特化类模板特化类模板特化指的是在类模板上,针对某些特定的类型和值,提供一种特殊的实现方式。类模板特化分为全特化和偏特化两种。类模板全特化定义......
  • C++提高编程
    C++提高编程本文主要针对C++泛型编程和STL技术做详细讲解,探讨C++更深层的使用1模板1.1模板的概念模板就是建立通用的模具,大大提高复用性例如生活中的模板一寸照片模板:PPT模板:模板的特点:模板不可以直接使用,它只是一个框架模板的通用并不是万能的1.2函数模板......
  • C++基础入门
    C++基础入门1C++初识1.1第一个C++程序编写一个C++程序总共分为4个步骤创建项目创建文件编写代码运行程序1.1.1创建项目​ VisualStudio是我们用来编写C++程序的主要工具,我们先将它打开1.1.2创建文件右键源文件,选择添加->新建项给C++文件起个名称,然后点击添......
  • C++ 使用getline()从文件中读取一行字符串
    我们知道,getline()方法定义在istream类中,而fstream和ifstream类继承自istream类,因此fstream和ifstream的类对象可以调用getline()成员方法。当文件流对象调用getline()方法时,该方法的功能就变成了从指定文件中读取一行字符串。该方法有以下2种语法格式:istream&......
  • VS Code配置C++开发环境(MSVC)
    前置知识这些内容如果感兴趣可以看一下,不看也不妨碍配置环境,因为我会一步步教你配置。(但我希望你还是看一下,毕竟我写了好久......