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

news2025/1/12 23:38:50

参考资料:

  • 《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.coloradmin.cn/o/1240414.html

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

相关文章

电子学会C/C++编程等级考试2022年12月(一级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:加一 输入一个整数x,输出这个整数加1后的值,即x+1的值。 时间限制:1000 内存限制:65536输入 一个整数x(0 ≤ x ≤ 1000)。输出 按题目要求输出一个整数。样例输入 9样例输出 10 答案: //参考答案: #include<bits/st…

全局定制序列化

作用:将返回实体类中的属性如果为null 变成"" package com.example.micrweb.config;import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.f…

OOM问题排查+Jvm优化

OOM问题排查&#xff1a; 1、top命令&#xff1a;查看cpu和内存的使用情况。 2、jstat命令&#xff1a;查看YGC和FGC情况&#xff0c;一般都是老年代不够用。导致OOM 3、jmap命令&#xff1a; 查看哪个类的实例过多,以每个类占用多少了内存。4、jstack 查看线程与线程之间的阻…

2019年12月 Scratch(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 怎样修改图章的颜色? A:只需要一个数字来设置颜色 B:设置RGB的值 C:在画笔中设置颜色、饱和度、亮度 D:在外观中设置或修改角色颜色特效 答案:D 在外观中设置或修改角色颜色特…

Impala VS Hive

Impala和Hive的关系 Impala是基于Hive的大数据实时分析查询引擎&#xff0c;直接使用Hive的元数据库Metadata,意味着impala元数据都存储在Hive的metastore中。并且impala兼容Hive的sql解析&#xff0c;实现了Hive的SQL语义的子集&#xff0c;功能还在不断的完善中。 与Hive的…

阿里云服务器ECS经济型e实例优惠99元性能怎么样?

阿里云服务器ECS经济型e实例优惠99元性能怎么样&#xff1f;阿里云服务器优惠99元一年&#xff0c;配置为云服务器ECS经济型e实例&#xff0c;2核2G配置、3M固定带宽和40G ESSD Entry系统盘&#xff0c;CPU采用Intel Xeon Platinum架构处理器&#xff0c;2.5 GHz主频&#xff0…

学习Opencv(蝴蝶书/C++)——3. OpenCV的数据类型

文章目录 1. 总览2. 基础类型2.0 基础类型总览2.1 cv::Vec<>类2.2 cv::Matx<>类2.3 cv::Point类(cv::Point3_< >和cv::Point_< >)2.4 cv::Scalar(cv::Scalar_)类2.5 cv::Size(cv::Size_)类、cv::Rect(cv::Rect_)类和cv::RotatedRect 类2.6 基础类型…

【Docker】从零开始:6.配置镜像加速器

【Docker】从零开始&#xff1a;5.配置镜像加速器 什么是镜像加速器&#xff1f;为什么要配置docker镜像加速器?常见的Docker镜像加速器有哪些&#xff1f;如何申请Docker镜像加速器如何配置Docker镜像加速器 什么是镜像加速器&#xff1f; 镜像加速器是一个位于Docker Hub之…

Niushop 开源商城 v5.1.7:支持PC、手机、小程序和APP多端电商的源码

Niushop 系统是一款基于 ThinkPHP6 开发的电商系统&#xff0c;提供了丰富的功能和完善的商品机制。该系统支持普通商品和虚拟商品&#xff0c;并且针对虚拟商品还提供了完善的核销机制。同时&#xff0c;它也支持新时代的商业模式&#xff0c;如拼团、分销和多门店砍价等营销活…

ESP32 Arduino实战Web篇-使用 WebSocket 创建 ESP32 Web 服务器

本文将详细介绍如何使用 WebSocket 创建 ESP32 Web 服务器,解释WebSocket原理与搭建步骤,并附超详细的代码解释 假设我们需要创建一个使用 ESP32 通过 WiFi 控制灯泡的项目。实现非常简单:我们将 ESP32 设置为软 AP 或 STA 模式,使其能够提供一个网页,显示灯开关的状态为…

Go语言多线程爬虫万能模板它来了!

对于长期从事爬虫行业的技术员来说&#xff0c;通过技术手段实现抓取海量数据并且做到可视化处理&#xff0c;我在想如果能写一个万能的爬虫模板&#xff0c;后期遇到类似的工作只要套用模板就能解决大部分的问题&#xff0c;如此提高工作效率何乐而不为&#xff1f; 以下是一个…

【Web】preg_match绕过相关例题wp

目录 ①[FBCTF 2019]rceservice ②[ctfshow]web130 ③[ctfshow]web131 ④[NISACTF 2022]middlerce 简单回顾一下基础 参考文章 p牛神文 preg_match绕过总的来讲就三块可利用 数组绕过、PCRE回溯次数限制、换行符 ①[FBCTF 2019]rceservice 先贴出附件给的源码 &l…

【算法】链表-20231123

这里写目录标题 一、19. 删除链表的倒数第 N 个结点二、21. 合并两个有序链表三、24. 两两交换链表中的节点 一、19. 删除链表的倒数第 N 个结点 提示 中等 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 输入&#xff1a;head [1,…

机器学习入门(第三天)——K近邻(物以类聚)

K-nearest neighbor 知识树 怎么区分红豆绿豆&#xff1f; How to distinguish red beans and green beans? 之前我们构造了一个超平面来解决这个问题&#xff0c;既然超平面可以切分&#xff0c;是不是红豆之间和绿豆之间有着某种关联。即&#xff1a;物以类聚。 如果一个…

【Axure高保真原型】树形表格

今天和大家分享树形表格的原型模板&#xff0c;点击树的箭头可以打开或者收起子节点&#xff0c;点击表格内容&#xff0c;可以选中该行内容实现高亮变色效果&#xff0c;树形表格是通过中继器制作的&#xff0c;使用简单&#xff0c;只需要按要求填写中继器表格即可&#xff0…

DedeBIZ 管理系统 DedeV6 v6.2.6 社区版 免费授权版

DedeBIZ 系统&#xff1a;开源、安全、高效的 DedeV6 v6.2.6 社区版 DedeBIZ 系统是基于 PHP 7 版本开发的&#xff0c;具有强大的可扩展性&#xff0c;并且完全开放源代码。它采用现流行的 Go 语言设计开发&#xff0c;不仅拥有简单易用、灵活扩展的特性&#xff0c;还具备更…

51单片机PWM控制LED灯渐明渐暗实验

51单片机PWM控制LED灯渐明渐暗实验 1.概述 这篇文章介绍单片机的PWM通过占空比控制LED灯的渐明渐暗效果&#xff0c;通过该实验掌握PWM的原理以及应用它做一些事情。 2.操作步骤 2.1.硬件电路 1.硬件准备 名称型号数量单片机STC12C20521LED彩灯无2晶振12MHZ1电容30pf2电阻…

SpringCloud - 新版淘汰 Ribbon,在 OpenFeign 中整合 LoadBalancer 负载均衡

目录 一、LoadBalancer 负载均衡 1.1、前言 1.2、LoadBalancer 负载均衡底层实现原理 二、整合 OpenFeign LoadBalancer 2.1、所需依赖 2.2、具体实现 2.3、自定义负载均衡策略 一、LoadBalancer 负载均衡 1.1、前言 在 2020 年以前的 SpringCloud 采用 Ribbon 作为负载…

边缘计算多角色智能计量插座 x 资产显示标签:实现资产追踪与能耗管理的无缝结合

越来越多智慧园区、智慧工厂、智慧医院、智慧商业、智慧仓储物流等企业商家对精细化、多元化智能生态应用场景的提升&#xff0c;顺应国家节能减排、环保的时代潮流&#xff0c;设计一款基于融合以太网/WiFi/蓝牙智能控制的智能多角色插座应运而生&#xff0c;赋予智能插座以遥…

Hadoop学习笔记:运行wordcount对文件字符串进行统计案例

文/朱季谦 我最近使用四台Centos虚拟机搭建了一套分布式hadoop环境&#xff0c;简单模拟了线上上的hadoop真实分布式集群&#xff0c;主要用于业余学习大数据相关体系。 其中&#xff0c;一台服务器作为NameNode&#xff0c;一台作为Secondary NameNode&#xff0c;剩下两台当…