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

news2024/11/28 16:28:34

参考资料:

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

9.3 顺序容器操作(P305)

9.3.1 向容器中添加元素(P305)

00418ca61cd635e0a466446a21be4f7

使用push_back

arrayforward_list 外,每个顺序容器都支持 push_back

vector<string> sentence;
while(cin >> word){
    sentence.push_back(word);
}

push_back 的调用相当于在容器尾部创建了一个新元素,将容器的 size 增大 1 ,该元素的值为 word拷贝

使用push_front

listforward_listdeque 还支持 push_front 操作,顾名思义就是把元素添加到容器头部。

在容器的特定位置添加元素

insert 提供了更一般的添加元素功能,它允许我们在容器中任意位置添加 0 个或多个元素。

每个 insert 函数都接受一个迭代器参数作为第一个参数,表示将元素插入到该迭代器所指位置之

插入范围内元素

insert 函数还可以接受更多参数,方式和容器构造函数类似:

vector<string> vs;
list<string> ls = {"hello", "world", "hi"};
vs.insert(vs.begin(), 10, "hi");
vs.insert(vs.begin(), ls.begin(), ls.end());
vs.insert(ls.begin(), ls.begin(), ls.end());    // 错误,拷贝范围和添加位置不能来自同一个容器

在新标准下,insert 返回第一个新加入元素的迭代器,如果没有新加入元素,则将参数迭代器返回。

使用insert的返回值

vector<int> vi = {0, 1, 2, 3, 4, 5};
auto it = vi.begin();
while(it != vi.end()){
    if(*it % 2){
        vi.insert(it, *it);
    }
    it++;
}
// vi的内容:0 1 1 2 3 3 4 5 5 

使用emplace操作

新标准引入了 emplace_frontemplaceemplace_back ,这些操作构造而不是拷贝元素。

调用 emplace 成员时,将参数传递给元素类型的构造函数直接构造元素:

// 使用三个参数的Sales_data构造函数
c.emplace_back("978-0590353403", 25, 15.99);

在调用 emplace_back 会在容器管理的内存空间中直接创建对象,push_back 则会创建一个局部临时对象,并将其压入容器中。

9.3.2 访问元素(P309)

f157ec230c56e627bb80437460f9693

访问成员函数返回的是引用

frontbackat 和下标返回的都是引用

下标操作和安全的随机访问

提供快速随机访问的容器都提供下标运算符越界的下标是一种严重的程序错误,而且编译器不会检查这种错误。

如果我们希望下标是合法的,可以使用 at 成员函数,如果下标越界,at 会抛出 out_of_range 异常。

9.3.3 删除元素(P311)

dd78ce4fc7a057ca0fc59432d94b8f5

pop_frontpop_back成员函数

二者的返回值均为 void

从容器内部删除一个元素

erase 从容器指定位置删除元素,可以删除一个由迭代器指定的单个元素,也可以删除由一对迭代器指定范围内的所有元素,返回删除的最后一个元素之后位置的迭代器。

// 删除奇数元素
vector<int> vi = { 0,1,2,3,4,5,6,7,8,9 };
auto cur = vi.begin();
while (cur != vi.end()) {
	if (*cur % 2) {
		cur = vi.erase(cur);
	}
	else {
		cur++;
	}
}

删除多个元素

vi.erase(vi.begin(), vi.end());

9.3.4 特殊的forward_list操作

回忆我们在数据结构中学过的知识,在单向链表中删除元素,往往需要用到待删除元素的上一个元素

由于删除方式的限制,forward_list 定义了 insert_afteremplace_aftererase_after 操作,也定义了 before_begin 来返回首前(off-the-beginning)迭代器

forward_list 中添加或删除元素时,我们必须同时关注指向待删除元素的迭代器和指向其前驱的迭代器:

// forward_list版删除奇数元素
forward_list<int> fi = { 0,1,2,3,4,5,6,7,8,9 };
auto pre = fi.before_begin();
auto cur = fi.begin();
while (cur != fi.end()) {
    if (*cur % 2) {
        cur = fi.erase_after(pre);
    }
    else {
        pre = cur;
        ++cur;
    }
}

9.3.5 改变容器大小(P314)

81e42c069a44d881ee3262939196fc8

我们可以用 resize 函数来增大或缩小容器,如果当前大小大于要求大小,容器后部的元素会被删除;如果当前大小小于要求大小,则会将新的元素添加到容器后面:

forward_list<int> fi = { 0,1,2,3,4,5,6,7,8,9 };
fi.resize(5);    // fi的内容:0,1,2,3,4
fi.resize(10, 5);    // fi的内容:0 1 2 3 4 5 5 5 5 5

9.3.6 容器操作可能使迭代器失效(P315)

向容器中添加元素或从容器中删除元素可能令指向容器元素的指针、引用、迭代器失效

向容器添加元素后:

  • 如果容器是 vectorstring ,且容器空间被重新分配,则指向容器的所有迭代器、指针、引用都会失效;如果容器空间没有被重新分配,则指向插入位置之前的元素的迭代器、指针、引用不会失效插入位置之后的迭代器、指针、引用会失效
  • 对于 deque 插入到除首尾位置之外的任何位置都会导致迭代器、指针、引用失效;如果在首尾位置添加元素,只会导致迭代器失效。
  • 对于 listforward_list ,指向容器的迭代器(包括尾后、首前)、引用、指针仍然有效。

从容器删除元素后:

  • 对于 listforward_list ,指向容器其他位置的迭代器(包括尾后、首前)、引用、指针仍然有效。
  • 对于 deque ,如果在首尾之外的任何位置删除元素,指向该容器中元素的迭代器、指针、引用都会失效;如果删除 deque 的尾元素,则尾后迭代器会失效,其他迭代器、指针、引用不受影响;如果删除首元素,除尾后迭代器外的其他迭代器、指针、引用不受影响(尾后迭代器是否会失效书里没说清楚)。
  • 对于 vectorstring ,指向被删元素之前元素的迭代器、指针、引用仍然有效,尾后迭代器总是会失效

不要保存end返回的迭代器

如果在一个循环中插入、删除 dequestringvector 中的元素,不要缓存 end 返回的迭代器。

9.4 vector对象是如何增长的

为了支持快速随机访问,vector 将元素存储在一片连续的空间中。如果添加元素时,vector没有足够的空间容纳新的元素,容器必须重新分配新的内存空间,将已有元素从旧位置移动到新空间中,然后添加新元素释放旧存储空间。

如果我们每添加一个元素就重新分配一次元素,那么性能将非常低。为此,标准库实现者通常会分配比需求更大的新内存空间,此时 vector 的扩张速度通常比 listdeque 还快。

管理容量的成员函数

e9bf4cce53b128bbca9b5913620623f

如果需求大小大于当前容量,reserve 至少分配与需求一样大的空间;如果需求大小小于等于当前容量,reserve 什么都不做。也就是说,调用 reserve 后,capacity 将大于传递给 reserve 的参数。

resize 成员只改变容器中的元素数量,而不是容器的容量:

// VS2022
vector<int> vi = {0};    // capacity = 1
vi.reserve(0);    // capacity = 1
vi.reserve(100);    // capacity = 100
vi.resize(0);    // capacity = 100, size = 0

shrink_to_fit 可以减少容器的容量,但其只是一个请求,具体的实现可以忽略此请求。

capacitysize

每个 vector 实现 都可以选择自己的内存分配策略,但必须遵守一条原则:只有当迫不得已时才可以重新分配策略。

通常来说,在一个空的 vector 上调用 n 次 push_back 的时间复杂度不能超过 n 的常数倍。

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

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

相关文章

MTK联发科MT8766核心板 4G智能模块安卓开发板方案定制

MT8766 是一款基于 MTK 平台工业级高性能、可运行 android12.0 操作系统的 4G智能模块,三款模块硬件是相互兼容&#xff0c;支持 LTE-FDD&#xff08;CAT-7&#xff09;/LTE-TDD&#xff08;CAT-7&#xff09;/WCDMA/TD-SCDMA/EVDO/GSM 等多种制式&#xff1b;支持 WiFi5 802.1…

(Matalb分类预测)WOA-BP鲸鱼算法优化BP神经网络的多维分类预测

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、部分程序&#xff1a; 四、完整代码数据使用手册下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matalb…

IDEA 快捷键汇总

目录 1、altinsert 2、ctrl/ 3、altenter 4、alt回车 5、ctrlD 6、ctrlaltL 7、ctrl点击 8、alt左键向下拉 9、ctrlaltv 10、ctrlaltwint 1、altinsert 快速创建代码&#xff0c;可以快速创建类中get set tostring等方法 2、ctrl/ 单行注释 3、altenter…

linux套接字-Socket

1.概念 局域网和广域网 局域网&#xff1a;局域网将一定区域内的各种计算机、外部设备和数据库连接起来形成计算机通信的私有网络。广域网&#xff1a;又称广域网、外网、公网。是连接不同地区局域网或城域网计算机通信的远程公共网络。IPInternet Protocol&#xff09;&#…

实用篇-ES-DSL查询文档

数据的存储不是目的&#xff0c;我们希望从海量的酒店数据中检索出需要的信息&#xff0c;这就是ES的搜索功能 官方文档: https://elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html#query-dsl。DSL是用来查询文档的 Elasticsearch提供了基于JSON的DSL来定…

SaaS与PaaS平台的区别

目录 一、前言 二、SaaS化与PaaS化平台的区别 三、PaaS化的低代码平台更胜一筹 PaaS优势&#xff1a; 支持PaaS服务的低代码平台 1.私有化部署&#xff0c;为数据安全保驾护航 2.业内领先技术&#xff0c;为开发强势赋能 3.超强集成能力&#xff0c;系统对接无忧 4.源代码交付&…

openEuler 系统操作 Docker Compose 容器化部署 Redis Cluster 集群的节点添加、删除和可视化监控

容器化部署 Redis Cluster 集群的节点添加、删除和可视化监控 Redis Cluster 集群回顾openEuler 系统查看端口是否被占用Redis Cluster 验证Redis CLI 客户端命令验证Redis GUI 工具验证宿主机安装 RedisInsightDocker 容器化部署 RedisInsight 添加集群节点启动 Reids 扩容服务…

接口自动化测试面试题

前言 前面总结了一篇关于接口测试的常规面试题&#xff0c;现在接口自动化测试用的比较多&#xff0c;也是被很多公司看好。那么想做接口自动化测试需要具备哪些能力呢&#xff1f; 也就是面试的过程中&#xff0c;面试官会考哪些问题&#xff0c;知道你是不是真的做过接口自动…

【Spring】 Spring中的IoC(控制反转)

以往在定义业务层实现时&#xff0c;在指定具体地Dao时候需要具体地定义出其实现&#xff1a; public class BookServiceImpl implements BookService{private BookDao bookDao new BookDaoImpl();public void save(){bookDao.save()} }public class BookDaoImpl implements …

python连接redis库

在自动化过程中&#xff0c;如果需要动态获取某个数据时&#xff0c;需要连接redis数据库。下面来详细介绍下如何操作。 redis这个库是python自带的&#xff0c;直接import导入即可,如下; import redis 1. redis 地址和端口&#xff0c;端口一般都是默认的6379,只需要换下地…

第08章 面向对象编程(高级)

一 关键字&#xff1a;static class Circle{private double radius;public Circle(double radius){this.radiusradius;}public double findArea(){return Math.PI*radius*radius;} }创建两个Circle对象&#xff1a; Circle c1new Circle(2.0); //c1.radius2.0 Circle c2new C…

python如何批量创建文件与文件夹

目录 一、引言 二、批量创建文件 1、使用os模块 2、使用pathlib模块 三、批量创建文件夹 1、使用os模块 2、使用pathlib模块 四、注意事项 五、总结与展望 一、引言 在Python中&#xff0c;我们经常需要创建文件和文件夹来存储和管理数据。批量创建文件和文件夹可以大…

实用技巧:在C和cURL中设置代理服务器爬取www.ifeng.com视频

概述&#xff1a; 网络爬虫技术作为一种自动获取互联网数据的方法&#xff0c;在搜索引擎、数据分析、网站监测等领域发挥着重要作用。然而&#xff0c;面对反爬虫机制、网络阻塞、IP封禁等挑战&#xff0c;设置代理服务器成为解决方案之一。代理服务器能够隐藏爬虫的真实IP地…

Everything——检索神兵

相信在日常生活工作中&#xff0c;大家肯定会有这样的困惑&#xff1a;由于一时疏忽&#xff0c;自己下载或编写的文件保存的路径丢失&#xff0c;想再次在茫茫内存中找到会很麻烦。今天学长将带来一款软件——Everything&#xff0c;其拥有强大的搜索功能&#xff0c;可以帮助…

UI游戏设计模板大放送:7种别具匠心的创意!

随着游戏产业的快速发展&#xff0c;UI游戏设计已经成为一个热门的设计行业&#xff0c;但与之前的设计相比&#xff0c;UI游戏设计还是比较特殊的&#xff0c;主要体现在UI游戏设计难度大&#xff0c;需要大量的手绘内容和对游戏玩法的理解上。这些门槛需要大量的时间去学习&a…

【Git学习一】初始化仓库git init的使用和提交git add与git commit的使用

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;Git等软件工具技术的使用 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要…

C++初阶-内存管理

内存管理 一、C/C内存分布二、C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free三、C内存管理方式new/delete操作内置类型new和delete操作自定义类型 四、operator new与operator delete函数operator new与operator delete函数 五、new和delete的实现原理内置类…

Abaqus2023新功能:分析技术

隐式耦合的松弛和加速器方法 产品&#xff1a;Abaqus/Standard SIMULIA协同仿真引擎现在支持Aitkens松弛方法以及Anderson和Broyden加速器方法&#xff0c;为强耦合物理场提供稳健且省时高效的解决方案。此功能在 2022 FD04 &#xff08;FP.2232&#xff09;版本中首次提供。…

文件包含_常见文件包含情况

文件包含系列 相关函数 分类 实践 包含实现的场景

解决编译时提示“没有那个文件或目录 #include <pcap.h>”的问题

解决编译时提示“没有那个文件或目录 #include 当你在编译代码时遇到“没有那个文件或目录 #include <pcap.h>”的错误提示&#xff0c;这通常意味着编译器在你的系统路径中找不到 pcap.h 头文件。pcap.h 是网络流量捕获库 pcap 的头文件&#xff0c;用于在 C/C 程序中捕…