C++中的顺序容器(一)

文章目录

  • 顺序容器概述
    • 所有容器类型都支持的操作
    • 迭代器
    • 容器定义与初始化
      • 将一个容器初始化为另一个容器的拷贝
      • 标准库array具有固定大小
    • 赋值和swap
    • 关系运算符
  • 顺序容器的特有操作
    • 向顺序容器添加元素
    • 访问元素
    • 删除元素
    • 特殊的forward_list操作
    • 改变容器的大小
    • 容器操作可能是迭代器失效

顺序容器概述

元素在顺序容器中顺序与其加入容器时的位置相对应。
在这里插入图片描述
选择合适的顺序容器:

  • 除非有很好的理由选择其他容器,否则使用vector;
  • 程序有很多小的元素,且空间的额外开销很重要,则不要使用list或forward_list;
  • 要求随机访问,vector、deque;
  • 要求在容器的中间插入或删除,list或forward_list;
  • 只在头尾插入或删除,deque;
  • 输入时要求在中间插入元素,随后要求随机访问:如果在中间插入只是为了排序的话,可以在vector尾部添加元素之后在使用sort排序;如果必须在中间插入,则可以先使用list接收数据,在将接收的数据拷贝到vector中。

如果不确定应该使用哪种容器,那么可以在程序中只是用vector或list公共的操作:使用迭代器,不使用下标操作,避免随机访问。

虽然我们可以在容器中保存几乎任何类型,但某些容器操作对元素类型有自己的特殊要求。例如顺序容器的一个版本的构造函数接收容器大小参数,并使用元素类型的默认构造函数。我们可以定义保存这种类型对象的容器,但在构造这种容器时不能只传递元素数量:

//假定noDefault是一个没有构造函数的类型
vector<noDefault> v1(10, init); //ok
vector<noDefault> v1(10); //err,必须提供一个元素初始化器

所有容器类型都支持的操作

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

迭代器

一个迭代器范围由一对迭代器表示,两个迭代器分别指向同一个容器中的元素或者尾元素之后的位置。可以使用begin得到第一个元素位置,end得到尾元素之后的位置。

//显式指定类型
list<string>::iterator it = a.begin();
list<string>::const_iterator it = a.begin();
//auto
auto it = a.begin(); //当a是const时,为const_iterator,否则为iterator
auto it = a.cbegin(); //const_iterator

当auto与begin或end结合使用时,获得的迭代器类型依赖于容器类型。但与cbegin或cend结合时,获得的是const_iterator。

容器定义与初始化

每个容器都定义了一个默认构造函数。除array之外,其他容器的默认构造函数都会创造一个指定类型的空容器。
在这里插入图片描述

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

将一个容器初始化为另一个容器的拷贝的方法有两种:

  • 可以直接拷贝整个容器,要求容器类型和元素类型必须匹配;
  • 拷贝由一个迭代器对指定的元素范围(array除外),不在要求要求容器类型和元素匹配,而要求拷贝的元素能够转化为目标元素即可。
list<string> authors = {"Mi", "Sh", "Au"};
vector<const char*> articles = {"a", "an", "the"};list<string> li(authors); //ok
deque<string> de(authors); //err
vector<string> words(articles); //err
//const char* 可以转换为string
forward_list<string> words(articles.begin(), articles.end()); //ok

标准库array具有固定大小

与内置数组一样,标准库array的大小也是类型的一部分。当定义一个array时,除了指定元素类型,还要指定容器大小:

array<int, 42> ia1; //42个默认初始化的int
array<int, 42> ia1 = {0}; //一个0,41个默认初始化的int
array<int, 42>::size_type i;

值得注意的是,内置数组不能进行拷贝或者赋值,但是array可以:

int digs[4] = {0, 1, 2, 3};
int cpy[4] = digs; //err,内置数组不支持拷贝或赋值
array<int, 4> digits = {0, 1, 2, 3}; //初始化后,不可使用{}赋值
array<int, 4> copy = digits; //ok,要求类型(容器类型以及大小)一致

赋值和swap

在这里插入图片描述
赋值运算符要求左右两边的运算对象具有相同的类型,它将右边运算对象中的所有元素拷贝到左边运算对象中。assign也可以实现类似的功能,但不在要求要求容器类型和元素匹配,而要求拷贝的元素能够转化为目标元素即可。

swap可以交换两个相同类型容器的内容。除了array之外,swap不会对任何元素进行拷贝、删除或插入操作,因此可以保证在常数时间完成,swap只是交换了两个容器之间的内部结构。这意味着指向容器(string除外)的迭代器、引用或指针在swap之后不会失效。

例如,iter在swap之前指向svec[3],在swap之后就会指向svec2[3]:

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

与其他容器不同,swap会真正交换array中元素,虽然swap不会使得array中的指针、引用、迭代器失效,但是在swap之后解引用得到的结果是另外一个array相应位置的值。

关系运算符

每个容器都支持相等运算符(==、!=),除了无序关联容器都支持关系运算符(>、>=、<、<=)。关系运算符左右两边运算对象必须是相同类型的容器,且必须保存相同类型的元素。并且只有当其元素也定义了相应的比较运算时,才可进行比较。

顺序容器的特有操作

向顺序容器添加元素

除array外,所有标准库容器都提供灵活的内存管理。在运行时可以动态添加或删除元素来改变容器的大小。
在这里插入图片描述
当我们用一个对象来初始化容器时,或将一个对象插入(push、insert)到容器时,实际上放入到容器中的是对象值得拷贝,而不是对象本身。值得注意得是,使用emplace时,则是将参数传递给元素得构造函数,并在容器内直接构造元素。

//使用三个参数构造函数
c.emplace_back("789", 25, 15.99);
//err
c.push_back("789", 25, 15.99);
//ok,创建一个临时对象传递给push
c.push_back(Sales_data("789", 25, 15.99));

访问元素

在这里插入图片描述
在容器中访问元素的成员函数返回的都是引用:

if(c.empty())
{c.front() = 42;auto &v = c.back();v = 1024; //改变容器中的元素auto v2 c.back;v2 = 0; //无法改变容器中元素
}

删除元素

在这里插入图片描述

特殊的forward_list操作

在这里插入图片描述
因为forward_list是单向列表,插入删除等操作会影响目标节点之前的节点,因此以目标节点的前节点作为参数。

改变容器的大小

在这里插入图片描述

容器操作可能是迭代器失效

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

添加、删除元素:

  • vector、string,且存储空间被重新分配,则指向容器的迭代器、指针和引用全部失效。如果为重新分配存储空间,则只失效指向插入后的元素的;
  • deque,插入删除到首尾之外的位置会导致指向其中元素的迭代器、指针和引用失效。
  • list、forward_list,不会失效;

使用失效的迭代器、指针或引用是严重的运行时错误。

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

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

相关文章

Javaweb中,使用Servlet编写简单的接口

案例&#xff1a;网页提交用户名和密码信息&#xff0c;后端校验密码长度需在6-12位之间 后端部分 WebServlet("/valid") public class SimpleServlet extends HttpServlet{public void service(HttpServletRequest req, HttpServletResponse resp) throws IOExcepti…

C语言实现的常见排序算法

排序是计算机科学中非常重要的基础算法之一。无论是在数据分析、数据库查询还是图形界面中&#xff0c;我们都可能会遇到排序问题。本文将介绍几种常见的排序算法&#xff0c;并提供其C语言实现代码。排序算法的效率和应用场景有很大关系&#xff0c;不同的算法有不同的时间复杂…

对于简单的HTML、CSS、JavaScript前端,我们可以通过几种方式连接后端

1. 使用Fetch API发送HTTP请求&#xff08;最简单的方式&#xff09;&#xff1a; //home.html // 示例&#xff1a;提交表单数据到后端 const submitForm async (formData) > {try {const response await fetch(http://your-backend-url/api/submit, {method: POST,head…

[论文阅读] SeeSR: Towards Semantics-Aware Real-World Image Super-Resolution

文章目录 一、前言二、主要贡献三、Introduction四、Methodology4.1 Motivation &#xff1a;4.2Framework Overview.** 一、前言 通信作者是香港理工大学 & OPPO研究所的张磊教授&#xff0c;也是图像超分ISR的一个大牛了。 论文如下 SeeSR: Towards Semantics-Aware Rea…

案例-04.部门管理-删除

一.功能演示 二.需求说明 三.接口文档 四.思路 既然是通过id删除对应的部门&#xff0c;那么必然要获取到前端请求的要删除部门的id。id作为请求路径传递过来&#xff0c;那么要从请求路径中获取&#xff0c;id是一个路径参数。因此使用注解PathVariable获取路径参数。 请求方…

Blazor-父子组件传递任意参数

在我们从父组件传参数给子组件时&#xff0c;可以通过子组件定义的[Parameter]特性的公开属性进行传值&#xff0c;但是当我们需要传递多个值的时候&#xff0c;就需要通过[Parameter]特性定义多个属性&#xff0c;有没有更简便的方式&#xff1f; 我们可以使用定义 IDictionar…

DeepSeek 的创新融合:多行业应用实践探索

引言 在数字化转型的浪潮中&#xff0c;技术的融合与创新成为推动各行业发展的关键力量。蓝耘平台作为行业内备受瞩目的创新平台&#xff0c;以其强大的资源整合能力和灵活的架构&#xff0c;为企业提供了高效的服务支持。而 DeepSeek 凭借先进的人工智能技术&#xff0c;在自然…

STM32创建静态库lib

创建静态库lib 1. 新建工程1.1 创建工程文件夹1.2 编写用户相关代码1.2.1 stm32f4xx_it.h1.2.2 stm32f4xx_it.c1.2.3 标准库配置&#xff1a;stm32f4xx_conf.h1.2.4 HAL库的配置&#xff1a;stm32f4xx_hal_conf.h1.2.5 LL库配置&#xff1a;stm32f4xx_ll_conf.h 1.3 移植通用文…

elabradio入门第二讲——BPSK数字调制与解调(插值、升余弦滤波、速率匹配、符号同步)

数字信号可以通过数字基带传输系统进行传输&#xff0c;而基带传输系统仅仅适用于低频信道下的数字信号传输。然而&#xff0c;在实际的通信系统中信道通常具有带通特性&#xff0c;因而需要将基带信号搬移到适合信道传输的高频载波上&#xff0c;使得信号与信道相匹配&#xf…

汽车 OTA 升级:提升下载与升级速度,优化用户体验

摘要&#xff1a; 随着汽车智能化的飞速发展&#xff0c;OTA&#xff08;Over - the - Air&#xff09;升级已成为汽车行业的重要技术&#xff0c;它能为车辆持续带来功能更新与性能优化。然而&#xff0c;下载及升级速度较慢的问题常常影响用户体验。本文深入探讨在汽车 OTA …

【Spring+MyBatis】留言墙的实现

目录 1. 添加依赖 2. 配置数据库 2.1 创建数据库与数据表 2.2 创建与数据库对应的实体类 3. 后端代码 3.1 目录结构 3.2 MessageController类 3.3 MessageService类 3.4 MessageMapper接口 4. 前端代码 5. 单元测试 5.1 后端接口测试 5.2 使用前端页面测试 在Spri…

SQLite Select 语句详解

SQLite Select 语句详解 SQLite 是一个轻量级的数据库管理系统&#xff0c;以其简洁的设计和高效的性能被广泛应用于各种场景。在 SQLite 中&#xff0c;SELECT 语句是用于查询数据库中的数据的命令。本文将详细介绍 SQLite 的 SELECT 语句&#xff0c;包括其基本语法、常用功…

深度学习05 ResNet残差网络

目录 传统卷积神经网络存在的问题 如何解决 批量归一化BatchNormalization, BN 残差连接方式 ​残差结构 ResNet网络 ResNet 网络是在 2015年 由微软实验室中的何凯明等几位大神提出&#xff0c;斩获当年ImageNet竞赛中分类任务第一名&#xff0c;目标检测第一名。获得CO…

组件库地址

react&#xff1a; https://react-vant.3lang.dev/components/dialoghttps://react-vant.3lang.dev/components/dialog vue用v2的 Vant 2 - Mobile UI Components built on Vue

docker 进阶命令(基于Ubuntu)

数据卷 Volume: 目录映射, 目录挂载 匿名绑定: 匿名绑定的 volume 在容器删除的时候, 数据卷也会被删除, 匿名绑定是不能做到持久化的, 地址一般是 /var/lib/docker/volumes/xxxxx/_data 绑定卷时修改宿主机的目录或文件, 容器内的数据也会同步修改, 反之亦然 # 查看所有 vo…

从入门到精通:Postman 实用指南

Postman 是一款超棒的 API 开发工具&#xff0c;能用来测试、调试和管理 API&#xff0c;大大提升开发效率。下面就给大家详细讲讲它的安装、使用方法&#xff0c;再分享些实用技巧。 一、安装 Postman 你能在 Postman 官网&#xff08;https://www.postman.com &#xff09;下…

将图片base64编码后,数据转成图片

将图片数据进行base64编码后&#xff0c;可以在浏览器上查看图片&#xff0c;只需在前端加上data:image/png;base64,即可 在线工具&#xff1a; Base64转图片 - 加菲工具

【动态规划】详解 0-1背包问题

文章目录 1. 问题引入2. 从 dfs 到动态规划3. 动态规划过程分析4. 二维 dp 的遍历顺序5. 从二维数组到一维数组6. 一维数组的遍历次序7. 背包的遍历顺序8. 代码总结9. 总结 1. 问题引入 0-1 背包是比较经典的动态规划问题&#xff0c;这里以代码随想录里面的例子来介绍下。总的…

LeetCode每日精进:20.有效的括号

题目链接&#xff1a;20.有效的括号 题目描述&#xff1a; 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以…

llama.cpp部署 DeepSeek-R1 模型

一、llama.cpp 介绍 使用纯 C/C推理 Meta 的LLaMA模型&#xff08;及其他模型&#xff09;。主要目标llama.cpp是在各种硬件&#xff08;本地和云端&#xff09;上以最少的设置和最先进的性能实现 LLM 推理。纯 C/C 实现&#xff0c;无任何依赖项Apple 芯片是一流的——通过 A…