C++初学者指南-5.标准库(第一部分)--容器遍历

C++初学者指南-5.标准库(第一部分)–容器遍历

文章目录

  • C++初学者指南-5.标准库(第一部分)--容器遍历
    • 前向遍历
      • 基于范围的循环
      • for_each / for_each_n
      • 迭代器的显式使用
      • 基于索引的循环
    • 逆向遍历
      • 反向范围循环(C++20)
      • 反向 for_each / for_each_n
      • 反向迭代器的显式使用
      • 基于索引的反向循环
    • 工具
      • 获取下一个/上一个迭代器
    • 相关内容

  • 尝试只在你想做的事情没有经过良好测试的(标准)库函数/算法的情况下编写循环!
  • 对于像std::vector这样的序列容器,首选非随机线性前向遍历,这得益于对缓存和预取的友好性
  • 只有一些标准容器支持反向遍历

前向遍历

基于范围的循环

for (type variable : container)

  • 适用于所有标准序列和关联式容器
  • 与容器无关⇒易于更改容器类型
  • 没有可能发生越界访问错误
  • 无需担心有符号/无符号的索引类型问题
  • 由于线性存取模式,使用序列容器时性能最佳 (缓存和预取友好)
  • 可以用break实现早期退出;
  • 不适合需要随机访问模式的算法
std::vector<Type> v {};
// 只读,类型的复制成本较低或者需要复制:
for (Type x : v) { cout << x; }
for (auto x : v) { cout << x; }
// 只读,类型复制的成本很高时:
for (Type const& x : v) { cout << x; }
for (auto const& x : v) { cout << x; }
// 修改值时:
for (Type& x : v) { cin >> x; }
for (auto& x : v) { cin >> x; }

for_each / for_each_n

  • 如果你已经有一个可以应用于每个元素的函数(对象),那会比较方便。
  • 适用于所有标准序列和关联容器。
  • 与容器无关⇒易于更改容器类型。
  • 无需担心有符号/无符号索引类型的麻烦。
  • 自说明性名称。
  • 使用迭代器范围可能存在越界访问错误。

在这里插入图片描述
不可能发生越界访问
cppreference

#include <algorithm>  // std::ranges::for_each
namespace ranges = std::ranges;  // alias
Container<Type> v;// 只读,类型的复制成本较低或者需要复制:
ranges::for_each(v, [](Type x){ cout << x; }); 
ranges::for_each(v, [](auto x){ cout << x; });
// 只读,类型复制的成本很高时:
ranges::for_each(v, [](Type const& x){ cout << x; });
ranges::for_each(v, [](auto const& x){ cout << x; });
// 修改值时:
ranges::for_each(v, [](Type& x){ cin >> x; });
ranges::for_each(v, [](auto& x){ cin >> x; });

在这里插入图片描述

  • 可用于子范围
  • 可能存在越界访问漏洞
    cppreference
#include <algorithm>  // std::for_each
Container<Type> v;// 只读,类型的复制成本较低或者需要复制:
for_each(begin(v), end(v),       [](Type x){ cout << x; });
for_each(begin(v)+2, begin(v)+5, [](auto x){ cout << x; });
// 只读,类型复制的成本很高时:
for_each(begin(v), end(v), [](Type const& x){ cout << x; });
for_each(begin(v), end(v), [](auto const& x){ cout << x; });
//修改值时:
for_each(begin(v), end(v), [](Type& x){ cin >> x; });
for_each(begin(v), end(v), [](auto& x){ cin >> x; });

在这里插入图片描述

  • 可用于子范围
  • 可能存在越界访问漏洞

迭代器的显式使用

  • 不受容器限制 ⇒ 容器类型易更改
  • 适用于所有标准序列容器
  • 无需担心有符号/无符号索引类型的麻烦
  • 可以跳过多个元素
  • 可能存在越界访问错误
  • 繁琐
std::vector<int> v {1, 2, 3, 4, 5, 6};
for (auto i = begin(v); i != end(v); ++i) { cout << *i; }
for (auto i = begin(v); i != end(v); ++i) { cin  >> *i; }
// 只读,使用常量迭代器
for (auto i = cbegin(v); i != cend(v); ++i { cout << *i; }

基于索引的循环

  • 可以跳过多个元素
  • 易受越界访问错误困扰
  • 由于有符号/无符号索引类型转换,很容易出现难以察觉的bug
  • 不适用于所有序列容器 ⇒ 不容易更改容器类型
  • 确保循环不修改元素需要更多的约束
  • 繁琐
std::vector<int> v {1, 2, 3, 4, 5, 6};
for (std::size_t i = 0; i < v.size(); ++i) { cout << v[i]; }
// 显式只读
const auto& cv = v;
for (std::size_t i = 0; i < cv.size(); ++i) { cout << cv[i]; }

逆向遍历

反向范围循环(C++20)

for (type variable : container | std::views::reverse)

  • 适用于所有双向容器
  • 不会出现越界访问错误
  • 不需要担心有符号/无符号索引类型的麻烦
  • 可以通过 break 实现提前退出
#include <ranges> //C++20
std::vector<int> v {1, 2, 3, 4, 5, 6};
for (int x : v | std::views::reverse) { cout << x << '\n'; }
// 只读,类型的复制成本较低或者需要复制:
for (auto x : v | std::views::reverse) { cout << x; }
// 只读,类型复制的成本很高时:
for (auto const& x : v | std::views::reverse) { cout << x; }
// 修改值时:
for (auto& x : v | std::views::reverse) { cin >> x; }

反向 for_each / for_each_n

  • 如果你已经有一个可以应用到每个元素的函数(对象),那是非常方便的
  • 适用于所有双向容器
  • 容易更改容器类型
  • 没有有符号/无符号索引类型的麻烦
  • 有界限迭代器访问的错误可能会发生
  • 具有自我说明的名称
    在这里插入图片描述
    不会发生越界访问
    cppreference
#include <algorithm>  // std::ranges::for_each
#include <ranges>     // range views
namespace ranges = std::ranges;        // alias
namespace views = std::ranges::views;  // alias
Container<Type> v;// 只读,类型的复制成本较低或者需要复制:
ranges::for_each(views::reverse(v), [](Type x){ cout << x; }); 
ranges::for_each(views::reverse(v), [](auto x){ cout << x; });
// 只读,类型复制的成本很高时:
ranges::for_each(views::reverse(v), [](Type const& x){ cout << x; });
ranges::for_each(views::reverse(v), [](auto const& x){ cout << x; });
// 修改值时:
ranges::for_each(views::reverse(v), [](Type& x){ cin >> x; });
ranges::for_each(views::reverse(v), [](auto& x){ cin >> x; });

在这里插入图片描述

  • 可用于子范围
  • 可能存在越界访问漏洞
    cppreference
#include <algorithm>  // std::for_each
Container<Type> v;// 只读,类型的复制成本较低或者需要复制:
for_each(rbegin(v), rend(v),       [](Type x){ cout << x; });
for_each(rbegin(v)+2, rbegin(v)+5, [](auto x){ cout << x; });
// 只读,类型复制的成本很高时:
for_each(rbegin(v), rend(v), [](Type const& x){ cout << x; });
for_each(rbegin(v), rend(v), [](auto const& x){ cout << x; });
// 修改值时:
for_each(rbegin(v), rend(v), [](Type& x){ cin >> x; });
for_each(rbegin(v), rend(v), [](auto& x){ cin >> x; });

在这里插入图片描述

  • 可用于子范围
  • 可能存在越界访问漏洞

反向迭代器的显式使用

  • 适用于所有双向容器
  • 无需担心有符号/无符号索引类型问题
  • 可以跳过多个元素
  • 可能出现越界访问错误
  • 繁琐
std::vector<int> v {1, 2, 3, 4, 5, 6};
for (auto i = rbegin(v); i != rend(v); ++i) { cout << *i; }
for (auto i = rbegin(v); i != rend(v); ++i) { cin  >> *i; }
// 只读,使用常量迭代器
for (auto i = crbegin(v); i != crend(v); ++i { cout << *i; }

基于索引的反向循环

  • 容易出现越界访问漏洞
  • 由于无符号大小类型而出现微妙错误容易编写:隐式转换为有符号整数,溢出/反转,…
  • 确保循环不修改元素需要更多约束
  • 繁琐
std::vector<int> v {1, 2, 3, 4, 5, 6};
// 标准容器使用无符号size类型
// ⇒ 注意不要减少无符号“0”
for (auto i = v.size(); i > 0; --i) { cout << v[i-1]; }
// 显式只读
const auto& cv = v;
for (auto i = cv.size(); i > 0; --i) { cout << cv[i-1]; }

工具

获取下一个/上一个迭代器

#include <iterator>
函数 std::prev 和 std::next 提供了一种通用的方式来递增/递减迭代器,即使迭代器类型不支持随机访问(例如,it += 5)。
然而,请注意,通过N步前进非随机访问迭代器(例如std::list中的迭代器)可能成本会很高,即涉及大约N个内存操作。

在这里插入图片描述
cppreference
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关内容

std::vector
标准库顺序容器
标准库关联容器
A Tour of C++: Containers and Algorithms

附上原文链接
如果文章对您有用,请随手点个赞,谢谢!^_^

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

k8s核心操作_存储抽象_K8S中使用Secret功能来存储密码_使用免密拉取镜像_k8s核心实战总结---分布式云原生部署架构搭建033

注意在看的时候一定要把 dxxxx中的xxxx换成--o----c----k----e----r 然后我们再来看一个k8s中的secret的功能,这个功能 用来存储密码的,configMap是用来存配置的 比如我们有个pod,他的镜像,如果是需要密码的,那么 我们现在是从公共仓库拉取的,如果我们从私有仓库拉取,有密码…

18_Shell好用工具:sort

18_Shell好用工具&#xff1a;sort 选项说明-k指定要排序的列-nnumber&#xff0c;按照数值大小排序-rreverse&#xff0c;逆序-t分隔符-u去重-o保存排序到文件 一、数字升序 #sort1.txt文件纯数字 #升序 sort -n sort1.txt #降序 sort -nr sort1.txt二、数字升序去重 #数字…

Java SpringAOP简介

简介 官方介绍&#xff1a; SpringAOP的全称是&#xff08;Aspect Oriented Programming&#xff09;中文翻译过来是面向切面编程&#xff0c;AOP是OOP的延续&#xff0c;是软件开发中的一个热点&#xff0c;也是Spring框架中的一个重要内容&#xff0c;是函数式编程的一种衍生…

【前端7*】表格-表单2(弹窗在子组件)父子组件调用 vue element-ui

vue element-ui 中表单弹框的使用 写在最前面一、子组件 HelloWorld.vue1. 弹窗部分、将 visible 传值给父组件2.表单的 ruleForm 校验方法3.表单确认方法4. 提交确认方法&#xff1a;handleSummit5.表单渲染 二、父组件 HomeView.vue1.新增按钮、查看和编辑2.引用子组件弹窗3.…

强化学习——多臂老虎机问题(MAB)【附python代码】

文章目录 一、问题描述1.1 问题定义1.2 形式化描述1.3 累积懊悔1.4 估计期望奖励 二、解决方法2.1 ϵ-贪婪算法2.2 上置信界算法2.3 汤普森采样算法2.4 小结 一、问题描述 1.1 问题定义 有一个用于 K 根拉杆的老虎机&#xff0c;每一根拉杆都对应一个关于奖励的概率分布 R 。每…

Python项目实战之-爬取全网小说资源

python爬虫实战-小说爬取 基于requests模块与lxml模块编写的爬虫 基本思路 主要内容分为三个部分 使用requests模块获取网页内容使用lxml模块进行网页解析将解析出来的数据存储进MySQL数据库中 获取网页内容 网站分析 获取各个分类的href标签 代码如下 def novel_sort…

JMeter接口测试之文件上传(参数提取与传递)

参考文档&#xff1a; Jmeter接口测试-文件上传&#xff08;全网最详细的教程&#xff09;_jmeter 文件上传-CSDN博客 1、首先通过fiddler抓取文件上传接口&#xff0c;在Raw的tab页中查看默认请求头以及请求参数 如图所示 2、在jmeter中导入抓取的接口&#xff0c;首先需要配…

ctfshow~菜狗杯 损毁的压缩包

题目给了一个.zip的压缩包&#xff0c;解压报错 用010Editor打开看一下&#xff0c;发现文件头是png的 把文件后缀改成png看一下&#xff0c;得到flag ctfshow{e19efe2eb86f10ccd7ca362110903c05}

【生命游戏】python刷题记录

目录 题目&#xff1a; 代码&#xff1a; 结果&#xff1a; 总结&#xff1a; 题目&#xff1a; 代码&#xff1a; class Solution:def gameOfLife(self, board: List[List[int]]) -> None:"""Do not return anything, modify board in-place instead.&…

rocky9.3操作系统安装记录

文章目录 一、镜像源二、安装的过程选择安装过程中语言安装信息摘要页面设置安装目的地设置管理员密码调整网络开始部署 一、镜像源 Rocky-9.3-x86_64-minimal.iso 二、安装的过程 选择安装过程中语言 安装信息摘要页面 设置安装目的地 不做操作&#xff0c;直接使用自动分…

2.10、matlab中字符、数字、矩阵、字符串和元胞合并为字符串并将字符串以不同格式写入读出excel

1、前言 在 MATLAB 中&#xff0c;可以使用不同的数据类型&#xff08;字符、数字、矩阵、字符串和元胞&#xff09;合并为字符串&#xff0c;然后将字符串以不同格式写入 Excel 文件。 以下是一个示例代码&#xff0c;展示如何将不同数据类型合并为字符串&#xff0c;并以不…

LoadRunner12通过代理录制脚本。

1、目前LR12录制脚本比较简单的方式有两种&#xff0c;还有一种是失败率太高 我这边基本没有成功过就不赘述了&#xff0c;这边写的是通过LR的代理服务器来进行录制。 2、首选配置LR的录制界面点击录制按钮&#xff0c;会显示出录制配置界面 3、在录制配置界面录制模式选择’通…

【C++刷题】[UVA 489]Hangman Judge 刽子手游戏

题目描述 题目解析 这一题看似简单其实有很多坑&#xff0c;我也被卡了好久才ac。首先题目的意思是&#xff0c;输入回合数&#xff0c;一个答案单词&#xff0c;和一个猜测单词&#xff0c;如果猜测的单词里存在答案单词里的所有字母则判定为赢&#xff0c;如果有一个字母是答…

性能测试工具原理与架构

在性能测试的学习过程中&#xff0c;坚持思想与工具&#xff08;分开&#xff09;并行&#xff0c;当前面世面上的性能测试书籍大多把理论与loadrunner融为一体讲解&#xff0c;这样做是正确的&#xff0c;因为有一些性能名词概念也源于工具。但是&#xff0c;性能测试不是load…

生物安全柜验证:气流流型、粒子、浮游菌等参考标准

生物安全柜也是制药行业常见设备&#xff0c;根据GMP的要求&#xff0c;需对生物安全柜定期进行验证确认&#xff0c;确保生物安全柜的性能满足GMP洁净厂房的相关要求。 生物安全柜是实验室的基本设备&#xff0c;也是生物安全实验室的一级安全隔离屏障。其最重要的作用就是气流…

简过网:公务员面试考什么?抓紧时间收藏!

你知道吗&#xff1f;在公务员考试中&#xff0c;其实笔试不是最难的&#xff0c;难的是面试&#xff0c;那么&#xff0c;公务员的面试都考什么呢&#xff1f;这篇文章告诉你答案&#xff01; ​ 对于公务员的面试一般可分为三种形式&#xff1a; 一、无领导&#xff1a; 什…

Unity | Shader基础知识(第十八集:Stencil应用-透视立方盒子)

目录 一、前言 二、场景布置 三、 shader部分 1.图片的部分 2.图片部分纯净代码 3.遮罩部分复习 4.深度写入 ZWrite 5.颜色遮罩ColorMask 6.遮罩纯净代码 四、场景中shader使用 五、作者的碎碎念 一、前言 因为这个内容稍微有点多&#xff0c;我尽力讲清楚了&#x…

Windows安装Nacos【超详细图解】

目录 一、下载 Nacos 二、解压 Nacos 三、编辑配置文件 四、创建数据库 五、启动 Nacos 六、进入控制台 一、下载 Nacos Nacos v2.3.2 官方网址 二、解压 Nacos 三、编辑配置文件 主要修改数据库用户名、密码、鉴权是否开启、key value和token # # Copyright 1999-2021 …

Fiddler抓包过滤host及js、css等地址

1、如上图所示 在Filter页面中勾选Hide if URL contains&#xff1b;输入框输入 REGEX:\.(js|css|png|google|favicon\?.*) 隐藏掉包含js、css、png、google等的地址&#xff1a; Hide if URL contains: REGEX:\.(js|css|png|google|favicon\?.*) 2、使Filters设置生效 A…

用Python实现学生信息管理系统

用Python来实现学生信息管理系统 学生信息管理系统&#xff08;Python&#xff09; 简介&#xff1a;基本信息管理和学生成绩管理。基本信息管理模块的主要功能有学生信息的添加、删除、修改、显示和学生数据的导入导出&#xff0c;学生成绩管理模块的主要功能有统计课程最高分…