C++20四大特性之Ranges

C++20 Ranges

  • 1.基础概念

  • 2.使用

在之前的文章已经写过另外三大特性,直通点:

C++那些事之C++20协程开篇

盘点C++20模块那些事

C++20:从0到1学懂concept

那么,本篇将开始学习另外一个特性ranges。

ranges是C++20的主要特性之一,其中"view"是比较重要的一部分。C++20之前,标准库的算法实现是基于迭代器来实现的,例如:std::sort。

std::sort(v.begin() + 2, v.end())

迭代器 + 算法能够完成一些复杂的操作,例如:我想要倒这排序:

std::sort(v.rbegin(), v.rend())

但是它也伴随着一些问题:

  • 容易混用两个不兼容的迭代器。

  • 算法的组合能力太弱,需要存储一些中间变量

例如:现在有一个学生信息系统,我们想要计算年龄在21-25区间且GPA >= 3.5,求取满足前面条件的学生总GPA。C++17之前我们可以写出下面这样的伪代码:

std::vector<Student> students
std::vector<Student> selected;
std::copy_if(students.begin(), students.end(), std::back_inserter(selected),[](const Student& student) {return student.age >= 21 && student.age <= 25 && student.gpa >= 3.5;});double s = std::accumulate(selected.begin(), selected.end(), 0.0,[](double sum, const Student& student) { return sum + student.gpa; });

可以看到我们在过滤前面满足条件的学生信息时需要将其拷贝到selected,然后再对其求和。

C++20 引入了一种更为简洁、高效的写法,通过使用范围和管道操作符 | 连接多个操作,可以在不需要中间变量的情况下直接求和,例如:

double s = 0.0;
for (const auto& student :students | std::views::filter([](const auto& s) {return s.age >= 21 && s.age <= 25 && s.gpa >= 3.5;}) | std::views::transform([](const auto& s) { return s.gpa; })) {s += student;
}

可以看到多个算法之间无缝衔接,减少了中间临时变量的内存分配,其可读性也大大增加,通过管道|将不同的操纵连接在一块。

接下来,让我们一起探讨C++20 ranges相关的内容。

1.基础概念

1.range

range 是一种表示一个序列的抽象概念。它可以是任何具有迭代器的容器或者是一个定义了 begin()end() 函数的对象。如 std::vectorstd::list 等都是范围的例子。对于数组,也可以视为范围。

2.view

view 是对 Range 的一种只读访问。它是一种惰性计算的方式,只有在需要的时候才会进行计算,这意味着它并不实际存储数据。例如:std::views::filterstd::views::transform 就是view的典型例子。它们允许我们对 range 进行筛选和转换,而不必实际创建新的容器。

3.algorithm

算法是对range或view进行操作的函数,例如:std::sortstd::find 等都是算法的例子。

4.|

管道操作符|,可以将视图与算法链接起来,将左侧的结果作为右侧的输入。它使得代码更为清晰、简洁。例如:students | std::views::filter(...)students 范围传递给 std::views::filter 进行过滤操作,然后再将结果传递给后续的操作。

以上面的student计算为示例,在这个例子中我们使用了范围students通过|作为视图filter的输入,然后将结果作为视图transform的输入,最后返回一个范围,基于这个范围进行循环,通过累加算法求和得到结果。

double s = 0.0;
for (const auto& student :students | std::views::filter([](const auto& s) {return s.age >= 21 && s.age <= 25 && s.gpa >= 3.5;}) | std::views::transform([](const auto& s) { return s.gpa; })) {s += student;
}

可以看到,使用range有如下好处:

  • 提高代码可读性

  • 懒惰计算:Ranges 引入了视图(view)的概念,允许懒惰计算,即在需要时才计算结果。

例如:只有在*v.begin()时才会去计算。

auto v = std::views::reverse(vec);
std::cout << *v.begin() << std::endl;
  • 减少错误:Ranges 的设计有助于减少一些传统迭代器操作中容易出现的错误,例如使用不兼容的迭代器。

  • 等等。

范围概念引入了不同的概念来描述不同类型的范围。这些概念有助于在泛型编程中更好地理解和限制范围的特性。以下是一些常用的范围概念:

https://en.cppreference.com/w/cpp/ranges

概念描述容器举例
std::ranges::input_range可以从头到尾至少迭代一次std::forward_list、std::list、std::duque、std::array、std::vector
std::ranges::forward_range可以从头到尾迭代多次std::forward_list、std::list、std::duque、std::array、std::vector
std::ranges::bidirectional_range迭代器也可以向后移动--std::list、std::duque、std::array、std::vector
std::ranges::random_access_range你可以在常数时间内跳转到元素 []std::duque、std::array、std::vector
std::ranges::contiguous_range元素总是连续存储在内存中std::array、std::vector

2.使用

使用这个特性比较简单,只需要引入头文件,使用接口即可。

例如:过滤一堆数字当中的偶数。

#include <ranges>
auto evenNumbers = numbers | std::views::filter([](int x) { return x % 2 == 0; });

编译:指定-std即可。

g++ -std=c++20 main.cc -o main

编译器支持可以阅读下面清单:

https://en.cppreference.com/w/cpp/compiler_support/20

gcc >=10,clang >=13(partial),>=15全面支持。


更多有趣内容,欢迎订阅知识星球~

4ed2e3853528ef5348933ed217482902.jpeg

de808599f3b626c0503b75df2ffa6024.jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/527587.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebRTC简介及实战应用 — 从0到1实现实时音视频聊天等功能

一、WebRTC简介 WebRTC 是由一家名为 Gobal IP Solutions,简称 GIPS 的瑞典公司开发的。Google 在 2011 年收购了 GIPS,并将其源代码开源。然后又与 IETF 和 W3C 的相关标准机构合作,以确保行业达成共识。其中: Web Real-Time Communications (WEBRTC) W3C 组织:定义浏览…

Nginx的页面优化,安全优化,日志分割,配置防盗链,图片缓存,解决部分问题

一、隐藏版本号 他人可以使用调试代理工具&#xff08;fiddler工具&#xff09;、浏览器插件等&#xff0c;通过识别网站的响应头信息来获取你的 Nginx 版本号。为了增强服务器的安全和隐私&#xff0c;可以进行隐藏版本号&#xff0c;也可以在 nginx.h 文件中修改服务名称和版…

力扣同类题:重排链表

很明显做过一次 class Solution { public:void reorderList(ListNode* head) {if(!head||!head->next)return;ListNode *fasthead,*lowhead;ListNode *prenullptr,*curnullptr,*nextnullptr;while(fast->next!nullptr){fastfast->next;if(fast->next)fastfast->…

Yolov8-pose关键点检测:特征融合涨点篇 | 广义高效层聚合网络(GELAN) | YOLOv9

💡💡💡本文独家改进:即结合用梯度路径规划(CSPNet)和(ELAN)设计了一种广义的高效层聚合网络(GELAN),高效结合YOLOv8-pose,实现涨点。 将GELAN添加在backbone和head处,提供多个yaml改进方法 Yolov8-Pose关键点检测专栏介绍:https://blog.csdn.net/m0_6377421…

开源组件安全风险及应对

在软件开发的过程中&#xff0c;为了提升开发效率、软件质量和稳定性&#xff0c;并降低开发成本&#xff0c;使用开源组件是开发人员的不二选择&#xff08;实际上&#xff0c;所有软件开发技术的演进都是为了能够更短时间、更低成本地构建软件&#xff09;。这里的开源组件指…

2023年终总结——跌跌撞撞不断修正

目录 一、回顾1.一月&#xff0c;鼓足信心的开始2.二月&#xff0c;焦躁不安3.三月&#xff0c;路还是要一步一步的走4.四月&#xff0c;平平淡淡的前行5.五月&#xff0c;轰轰烈烈的前行6.六月&#xff0c;看事情更底层透彻了7.七月&#xff0c;设计模式升华月8.八月&#xff…

前端WebRTC局域网1V1视频通话

基本概念 WebRTC&#xff08;Web Real-Time Communications&#xff09; 网络实时通讯&#xff0c;它允许网络应用或者站点&#xff0c;在不借助中间媒介的情况下&#xff0c;建立点对点&#xff08;Peer-to-Peer&#xff09;的连接&#xff0c;实现视频流和音频流或者其他任…

智慧公厕_智慧化的公厕_智慧公厕系统_智慧公厕管理系统

一、什么是智慧公厕系统&#xff1f; 智慧公厕系统是一种利用物联网、互联网、大数据、云计算等前沿技术&#xff0c;将公共厕所信息化、数字化、智能化的系统。随着科技的进步&#xff0c;智慧公厕系统成为城市建设的一个重要部分&#xff0c;&#xff08;ZonTree中期科技&am…

软文营销的误区及提高推广效果的方法

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 一&#xff0c;软文营销的五大误区 误区一&#xff1a;需要时才做推广 问题&#xff1a;许多企业在需要快速获得曝光或销售提升时才考虑软文营销&#xff0c;但这样零散的推广很难形成…

MySQL 的基础操作

数据库的基础操作 1. 库操作2. 表的操作3. 数据类型 数据库是现代应用程序中至关重要的组成部分&#xff0c;通过数据库管理系统&#xff08;DBMS&#xff09;存储和管理数据。 1. 库操作 创建数据库 创建数据库是开始使用数据库的第一步。下面是一些常见的创建数据库的示例&a…

深入了解二叉搜索树:原理、实现与应用

目录 一、介绍二叉搜索树 二、二叉搜索树的基本性质 三、二叉搜索树的实现 四、总结 在计算机科学中&#xff0c;数据结构是构建算法和程序的基础。其中&#xff0c;二叉搜索树&#xff08;Binary Search Tree&#xff0c;简称 BST&#xff09;作为一种常见的数据结构&#…

AHU 人工智能实验-CCA

神经网络覆盖算法——CCA&#xff08;基于Ling Zhang 和Bo Zhang论文) Abstract 在这篇文章中我将介绍基于张铃和张钹学者提出的CCA算法&#xff0c;并实现代码复现&#xff0c;给出使用的数据集&#xff0c;以及实验结果对比。 1. Introduction 1.1 Background 我们知道自…