《C++ Primer》第9章 顺序容器(一)

参考资料:

  • 《C++ Primer》第5版
  • 《C++ Primer 习题集》第5版

C++ 中的容器可以分为 3 类:顺序容器、关联容器、无序关联容器。

9.1 顺序容器概述(P292)

所有顺序容器都提供了快速顺序访问的能力,但在以下方面的性能有所不同:

  • 向容器添加、删除元素
  • 非顺序访问容器中的元素
f627822bfcf591e09297d8c54ea16f6

除了固定大小的 array 外,其他容器提供高效、灵活的内存管理。不同的存储管理策略,将会影响容器操作的效率以及是否支持特定操作:

  • stringvector 将元素保存在连续的空间中,所以支持随机访问,但在中间位置添加或删除元素就非常耗时。添加一个元素可还需要分配额外的存储空间,此时容器中的每个元素都将移动到新的存储空间中。
  • listforward_list 可以快速在任何位置添加或删除元素,但不支持随机访问。这两个容器的额外内存开销也较大。
  • deque 支持快速随机访问,在中间位置添加或删除元素代价高,但在两端添加或删除元素的速度与 listforward_list 相当。

forward_listarray 是 C++ 新标准新添加的类型。array比内置数组更安全、更易使用的数组类型;forward_list 的设计目标是达到与最好的手写单向链表相当的性能,所以其没有 size 操作,因为这会产生额外开销。

新标准库的容器性能很高,所以现在 C++ 程序应该更多地使用标准库容器

确定使用哪种顺序容器

选择容器的基本原则:

  • 除非有很好的理由选择其他容器,否则选择 vector
  • 如果你的程序有很多小的元素,且空间开销很重要,则不要使用 listforward_list
  • 如果程序要求随机访问元素,使用 vectordeque
  • 如果程序要求在中间插入或删除元素,使用 listforward_list
  • 如果程序要求在头尾插入或删除元素,使用 deque

9.2 容器库概览(P294)

本小节介绍的操作对所有容器都适用。

对容器可以保存的元素类型的限制

虽然顺序容器几乎可以保存任何元素类型,但某些容器操作需要对元素类型有特殊要求。例如,顺序容器的构造函数的一个版本接受容器大小参数,它使用了元素的默认构造函数,但如果某个类没有默认构造函数,我们可以定义这个类的顺序容器,但不能适用这个版本的构造函数:

// noDefault是一个没有默认构造函数的类型
vector<noDefault> v1(10);    // 错误
29e8544c53327ded26bb254e5671959 6ac59aaab389613cab138b0a99b6d6c

9.2.1 迭代器(P296)

迭代器范围

一个迭代器范围(iterator range)一对迭代器表示,这两个迭代器通常被称为 beginend ,并满足如下要求:

  • 它们指向同一个容器中的元素,或容器的尾后位置。
  • 可以通过大于等于 0 次递增运算,使 begin 到达 end

迭代器范围是一个左闭右开区间。

适用左闭合范围蕴含的编程假定

左闭合范围有一些方便的性质:

  • 如果 beginend 相等,则范围为空。
  • 如果 beginend 不等,则范围中至少包含一个元素,且 begin 指向范围中的首元素。
  • 我们可以对 begin 递增若干次,使得 begin == end

9.2.2 容器类型成员97)

每个容器都定义了很多类型,如 size_typeiteratorconst_iterator 。大多数容器还提供反向迭代器,执行 ++ 操作会得到上一个元素。

每个容器还定义了很多类型别名,如 value_typereferenceconst_reference

为了使用这些类型,我们必须显式使用类名:

list<string>::iterator iter;
vector<int>::difference_type count;

9.2.3 beginend成员(P298)

不以 c 开头的 beginend 函数都是被重载过。例如,实际上存在两个名为 begin 的成员,一个是 const 的,返回 const_iterator ,另一个不是常量,返回 iterator

c 开头的版本是 C++ 新标准引入的,用以支持 autobeginend 结合使用:

vector<int> vi(5);
auto it1 = a.begin();
auto it2 = a.cbegin();

练习

9.10 :下面四个对象分别是什么类型?

vector<int> v1;
const vector<int> v2;
auto it1 = v1.begin(), it2 = v2.end();
auto it3 = v1.cbegin(), it4 = v2.cend();

答:第一条 auto 语句显然是不正确的,第二条 auto 语句解析出的类型是 vector<int>::const_iterator

9.2.4 容器定义和初始化(P299)

338e6c1e4a65a4176658be324ec7d17

将一个容器初始化为另一个容器的拷贝

将一个容器初始化为另一个容器的拷贝的方式有两种:直接拷贝整个容器、( array 除外)拷贝由一对迭代器指定的元素范围。

直接拷贝整个容器时,需保证容器类型和元素类型完全相同;范围拷贝只要求能将被拷贝的元素类型转换成目标类型即可:

list<string> ls = { "hello", "hi", "world" };
vector<const char *> vcc = { "a", "an", "the" };

list<string> ls1(ls);    // 正确
deque<string> ds(ls);    // 错误,容器类型不相同
vector<string> vs(vcc);    // 错误,元素类型不相同
forward_list<string> fls(vcc.begin(), vcc.end());    // 正确

范围初始化用被拷贝容器中的元素对目标容器中的对应元素进行初始化。

列表初始化

在新标准中,我们可以对一个容器进行列表初始化。对于除 array 之外的容器类型外,初始化列表还隐含指定了容器的大小

与顺序容器大小相关的构造函数

只有顺序容器的构造函数才接受大小参数。

标准库array具有固定大小

定义一个 array 容器时,除了要指定元素类型外,还要指定容器大小:

array<int, 42> ai;

大小是 array 类型的一部分:

array<int, 10>::size_type i;
array<int>::size_type j;    // 错误

与内置数组不同的是,array 支持拷贝、赋值操作,此时要求容器类型、元素类型、元素个数都一样。

9.2.5 赋值和swap(P302)

d4b62816911145eae5b9855e856879e

赋值操作 c1 = c2c1 中的元素替换为 c2 中元素的拷贝,要求 c1c2 必须具有相同的类型(容器类型、元素类型,array 还额外要求元素数量)。

使用assign(仅顺序容器)

assign 允许我们从一个不同但相同的类型赋值:

list<string> ls = { "hello", "hi", "world" };
vector<const char *> vcc = { "a", "an", "the" };

ls = vcc;    // 错误
ls.assign(vcc.begin(), vcc.end());    // 正确

使用swap

swap 可以交换两个相同类型容器的内容:

vector<string> svec1(10);
vector<string> svec2(20);
swap(svec1, svec2);

单独提起“相同类型容器”,其实就等价于容器类型相同、元素类型相同、元素数量相同(仅 array)。

array 外,swap 并不会真的交换元素本身,所以效率很高,可以在常数时间完成。由于元素不会被移动, string ,指向容器的迭代器、引用、指针在 swap 操作后不会失效,它们仍然指向原来的元素,但这些元素已经不属于原来的容器了

arrayswap 操作会真正交换元素,所需时间与元素数量成正比。swap 操作后,迭代器、引用、指针扔指向原来的元素,但元素值已经进行了交换

建议使用非成员版本的 swap

9.2.6 容器大小操作(P304)

forward_list 外,每个容器都支持 sizeemptymax_sizeforward_list 只支持前两个。

9.2.7 关系运算符(P304)

每个容器类型都支持 ==!= ;除无序关联容器外的所有容器都支持 >>=<<= 。关系运算符要求左右两边对象有相同的容器类型。

两个容器的比较实际上是元素的逐对比较:

  • 逐个比较元素,一旦遇到不相等的情况,就用这对不相等元素的比较结果作为容器的比较结果
  • 如果没有遇到不相等的情况,此时用元素数量的比较结果作为容器的比较结果

容器的关系运算符使用元素的关系运算符完成

容器的 ==!= 实际上是使用元素== 实现的,其他运算符是使用元素< 实现的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jjwt使用说明-笔记

jjwt官网链接&#xff1a;https://github.com/jwtk/jjwt POM 依赖 <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.12.3</version> </dependency> <dependency><grou…

Web前端—移动Web第五天(媒体查询、Bootstrap、综合案例-alloyTeam)

版本说明 当前版本号[20231122]。 版本修改说明20231122初版 目录 文章目录 版本说明目录移动 Web 第五天01-媒体查询基本写法书写顺序案例-左侧隐藏媒体查询-完整写法关键词 / 逻辑操作符媒体类型媒体特性 媒体查询-外部CSS 02-Bootstrap简介使用步骤下载使用 栅格系统全局…

易点易动库存管理系统革新企业库存管理,降本增效

随着全球经济的快速发展和市场竞争的加剧&#xff0c;企业对库存管理的需求变得越来越迫切。传统的手工操作和繁琐的库存管理方式已经无法满足现代企业的需求。为了解决这一问题&#xff0c;易点易动库存管理系统应运而生。 易点易动库存管理系统概述 易点易动库存管理系统是一…

快速上手Banana Pi BPI-M4 Zero 全志科技H618开源硬件开发开发板

Linux[编辑] 准备[编辑] 1. Linux镜像支持SD卡或EMMC启动&#xff0c;并且会优先从SD卡启动。 2. 建议使用A1级卡&#xff0c;至少8GB。 3. 如果您想从 SD 卡启动&#xff0c;请确保可启动 EMMC 已格式化。 4. 如果您想从 EMMC 启动并使用 Sdcard 作为存储&#xff0c;请确…

220V转12V固定输出12V非隔离芯片WT5106WT5105

220V转12V固定输出12V非隔离芯片WT5106WT5105 今天给大家介绍一款实用芯片&#xff0c;WT5106。它是一款高效率高精度的非隔离降压开关电源恒压控制驱动芯片。 WT5106适用于85VAC~265VAC全范围输入电压的非隔离Buck、Buckboost拓扑结构&#xff0c;小家电、电机驱动、继电器驱…

分布式篇---第一篇

系列文章目录 文章目录 系列文章目录前言一、分布式幂等性如何设计?二、简单一次完整的 HTTP 请求所经历的步骤?三、说说你对分布式事务的了解前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,…

【HarmonyOS】 API9 Stage模型 MD5加密字符串

在API9 Stage 模型中使用MD5加密&#xff0c;使用ohpm的三方库"ohos/crypto-js"进行加密操作 【集成步骤】 1、在entry-oh-package.json5中添加"ohos/crypto-js"依赖&#xff0c;点击sync同步依赖&#xff0c;crypto-js最新版本是2.0.2只支持API10&#x…

字符串和内存函数(2)

文章目录 2.13 memcpy2.14 memmove2.15 memcmp2.16 memset 2.13 memcpy void* memcpy(void* destination, const void* source, size_t num); 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。这个函数在遇到 ‘\0’ 的时候并不会停下来。如果so…

永久免费!N个excel表一键合并成一个表(excel表格合并技巧)

您是否还在用手工复制粘贴来将多个EXCEL或表的数据合并到一个表里&#xff1f;那就太麻烦&#xff0c;效率太低了&#xff0c;用金鸣表格文字识别的“表格合并”功能&#xff0c;可免费将N个excel文件或N个excel表一键合并到一个表里面&#xff0c;而且这个功能永久免费&#x…

ubuntu22.04安装网易云音乐

附件&#xff1a; https://download.csdn.net/download/weixin_44503976/88557248 wget https://d1.music.126.net/dmusic/netease-cloud-music_1.2.1_amd64_ubuntu_20190428.deb wget -O patch.c https://aur.archlinux.org/cgit/aur.git/plain/patch.c?hnetease-cloud-m…

山西电力市场日前价格预测【2023-11-24】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-11-24&#xff09;山西电力市场全天平均日前电价为415.13元/MWh。其中&#xff0c;最高日前电价为685.26元/MWh&#xff0c;预计出现在18:00。最低日前电价为296.84元/MWh&#xff0c;预计…

重磅!2023年两院院士增选名单公布

中国科学院 关于公布2023年中国科学院院士增选当选院士名单的公告 根据《中国科学院院士章程》《中国科学院院士增选工作实施办法&#xff08;试行&#xff09;》等规定&#xff0c;2023年中国科学院选举产生了59名中国科学院院士。 现予公布。 中国科学院 2023年11月22日…

内衣洗衣机哪些品牌质量好实惠?小型洗衣机全自动

现在洗内衣内裤也是一件较麻烦的事情了&#xff0c;在清洗过程中还要用热水杀菌&#xff0c;还要确保洗衣液是否有冲洗干净&#xff0c;还要防止细菌的滋生等等&#xff0c;所以入手一款小型的烘洗全套的内衣洗衣机是非常有必要的&#xff0c;专门的内衣洗衣机可以最大程度减少…

Altium Designer学习笔记10

再次根据图纸进行布局走线&#xff1a; 这个MT2492 建议的布局走线。 那我这边应该是尽量按照该图进行布局&#xff1a; 其中我看到C1的电容的封装使用的是电感的封装&#xff0c;需要进行更换处理&#xff1a; 执行Validate Changes和Execute Changes操作&#xff0c;更新&a…

11月23日星期四今日早报简报微语报早读

11月23日星期四&#xff0c;农历十月十一&#xff0c;早报微语早读。 1、我国5G基站总数达321.5万个&#xff1b; 2、2023年两院院士增选结果揭晓&#xff0c;共133人当选&#xff1b; 3、北京低保标准提升至每人每月1395元&#xff1b; 4、上海制定体育发展条例&#xff1a…

C++数组中重复的数字

3. 数组中重复的数字 题目链接 牛客网 题目描述 在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 Input: {2, 3, 1, 0, 2, 5}Output: 2解题…

Postgres 数据库中 ULID 和 UUID 的性能

大家好&#xff01;在本文中&#xff0c;我想分享我对经常用作标识符的数据类型的知识和看法。今天我们将同时讨论两个主题。这些是数据库端按键和键的数据类型衡量的搜索速度。 我将使用PostgreSQL数据库和演示Java服务来比较查询速度。 UUID 和 ULID 为什么我们需要某种难…

【Java工具篇】Java反编译工具Bytecode Viewer

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

解决 requests 库上传大文件速度慢的问题:从问题原因到解决方案

在我的加班日志里&#xff0c;经常会有一些日期和事件&#xff0c;这次我要写的是2023-03-24&#xff0c;当时的事件是追bug。 我遇到了一个困扰已久的问题&#xff0c;就是requests库上传大文件的速度非常慢。这个问题让我很头疼&#xff0c;因为我正在处理一个需要大量上传文…

浅谈JDK动态代理(中)

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 动态代理的使命 在做日…
最新文章