C/C++STL学习[1]---顺序容器阐述、对比、选择vector,deque,list,forward_list,array,string

2023-12-05

前言

STL系列博客开篇,记录一下自己学C++STL相关的心得。
这篇博客主要是写顺序容器的类型以及各个容器之间的异同还有平时对容器使用的选择。


1. 顺序介绍

顺序容器表示这个容器提供了快速顺序访问元素的能力。

下面是常用的一些顺序容器:

容器名称 简述
vector 可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢
deque 双端队列。支持快速随机访问。在头尾位置插入/删除速度很快
list 双向链表。只支持双向顺序访问。在list中任何位置进行插入/删除操作速度都很快
forward_list 单向链表。只支持单向顺序访问。在链表任何位置进行插入/删除操作速度都很快
array 固定大小数组。支持快速随机访问。不能添加或删除元素
string 与vector相似的容器,但专门用于保存字符。随机访问快。在尾部插入/删除速度快

2. 容器对比说明

array与vector

array就是我们使用的数组。我们一般使用数组的时候都是这样定义的 int a[10] ,这个表示我定义了一个存放int类型数据的数组,数组长度为10。但是我们存放数据的时候,数据会一直增加,很难确定应该给多大的容量才可以保证既不浪费内存又能够满足我们需求。

在我学STL之前,刷题的时候喜欢定义数组。比如要输入20个数据,我就给他定义个25个长度的数组。或者对于不可确定的长度,我往往定义很大的数组。这就导致内存总是过大,影响程序执行时间。

针对这种情况,STL中出现了vector。它解决了array的不可变长度问题。可以把它看成是一个可变长的数组。对于array的数据插入,如果新数据不在尾部插入的话,就意味着数据就要产生移动。比如长度为10的数组,我已存放4个数据,我现在想在第2个位置插入数据,这时候,后面的3,4位数据就要依次往后移动一个单位长度。如果数据量很大,这就导致插入效率很低。vector是array的变形,从定长转向不定长,但是由于存储方式的原因,它还是无法解决这种中途插入带来的效率低问题。但是由于是顺序插入,所以可以用 下标 的方式进行数据读取。这个就是它的优点:支持快速随机访问。


vector与string

string和vector都是将元素保存在连续的内存空间中。string是专门存放字符的一种vector容器(这是我自己理解的)。所以vector的特性string都有,比如快速随机访问,以及中间插入很慢,尾部插入或者删除很快。


list与forward_list
有前面的连续内存分配方式,就会有分散的内存分配方式。前者的优点是支持快速随机访问,后者就需要依次遍历。后者通常采用链表的方式进行数据存储。

list就是一个双端的链表。这说明list支持头插和尾插。这个和双端队列deque很相似。forward_list直译过来就是前端队列,这说明forward_list只支持从链表头进行插入数据。这两个容器的好处就是解决了上面array,vector,string三种容器插入删除中间元素过慢的问题,因为是链表存储,所以不涉及到依次移动元素。但是元素的访问必须要依次遍历每一个元素。


deque与其他容器
deque是一个双端队列,更加复杂一些。deque存放数据是连续内存分配的方式,所以和string,vector一样,支持快速随机访问。同样的,不可避免的就是中间插入或删除元素的代价可能很高。

但是在deque的两端添加或删除元素都是很快的,与list或forward_list添加删除元素的速度相当。

我个人理解是,deque是既想要有快速访问的效果,但是又想提高元素的插入删除的效率。但由于是内存的连续分配,所以不可避免插入的效率低,只能通过改变插入的位置来提高效率,就有了头尾插法。


3. 容器选择

没学STL之前嘛,那就是直接一个数组,顶多再来个链表搞定所有。学了之后,这么多种容器,怎么选?下面是一些参考意见。

通常使用了STL的话,vector是最好的选择。

  • 除非你有很好的理由选择其他容器,否则应使用vector。
  • 如果你的程序有很多小的元素,且空间的额外开销很重要,则不要使用list或forward_list。
  • 如果程序要求随机访问元素,应使用vector或deque。
  • 如果程序要求在容器的中间插入或删除元素,应使用list 或forward_list。·如果程序需要在头尾位置插入或删除元素,但不会在中间位置进行插入或删除操作,则使用deque。
  • 如果程序只有在读取输入时才需要在容器中间位置插入元素,随后需要随机访问元素,则
    首先,确定是否真的需要在容器中间位置添加元素。当处理输入数据时,通常可以很容易地向vector追加数据,然后再调用标准库的sort函数来重排容器中的元素,从而避免在中间位置添加元素。
    如果必须在中间位置插入元素,考虑在输入阶段使用list,一旦输入完成,将list中的内容拷贝到一个vector中。

如果程序既需要随机访问元素,又需要在容器中间位置插入元素,那该怎么办?答案取决于在list或forward_list中访问元素与vector或deque 中插入/删除元素的相对性能。一般来说,应用中占主导地位的操作(执行的访问操作更多还是插入/删除更多)决定了容器类型的选择。在此情况下,对两种容器分别测试应用的性能可能就是必要的了。
如果你不确定应该使用哪种容器,那么可以在程序中只使用vector和list

公共的操作:使用迭代器,不使用下标操作,避免随机访问。这样,在必要时选择使用vector或list都很方便。


总结

第一次看完之后还是有些笼统,写这篇博客的时候又复盘了一遍,印象更加深刻一些。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C/C++STL学习[1]---顺序容器阐述、对比、选择vector,deque,list,forward_list,array,string 的相关文章

  • 有没有快速创建集合的方法?

    目前我正在创建一个像这样的新集 std set a s s insert a1 s insert a2 s insert a3 s insert a10 有没有办法创建s在一行 int myints 10 20 30 40 50 std s
  • QCombobox 向下箭头图像

    如何更改Qcombobox向下箭头图像 现在我正在使用这个 QSS 代码 但这不起作用 我无法删除向下箭头边框 QComboBox border 0px QComboBox down arrow border 0px background
  • 如何保证对象只有一个线程

    我有以下代码 class Service public void start creates thread which creates window and goes to message loop void stop sends WM C
  • FileStream 构造函数和默认缓冲区大小

    我们有一个使用 NET 4 用 C 编写的日志记录类 我想添加一个构造函数参数 该参数可以选择设置文件选项 WriteThrough http msdn microsoft com en us library system io fileo
  • EF Core 通过完全替换断开集合导航属性的更新

    使用 EF Core 5 0 我有一个 SPA 页面 可以加载Group实体及其集合Employee来自 API 的实体 var groupToUpdate await context Groups Include g gt g Emplo
  • 我如何在 C# .NET(win7 手机)中使用“DataContractJsonSerializer”读入“嵌套”Json 文件?

    我有一个问题 如果我的 json 文件看起来像这样 Numbers 45387 Words 空间桶 我可以很好地阅读它 但是如果它看起来像这样 Main Numbers 45387 Words 空间桶 某事 数字 12345 单词 克兰斯基
  • 根据 N 个值中最小的一个返回不同的结果

    不确定如何使标题更具描述性 所以我只是从一个例子开始 我使用下面的代码位 它从枚举中选择一个方向 具体取决于四个轴中哪一个与给定方向相比形成最小角度 static Direction VectorToDirection Vector2 di
  • 与 Qt 项目的静态链接

    我有一个在 Visual Studio 2010 Professional 中构建的 Qt 项目 但是 当我运行它 在调试或发布模式下 时 它会要求一些 Qt dll 如果我提供 dll 并将它们放入 System32 中 它就可以工作 但
  • 指向特征矩阵的指针数组

    我在代码中使用 Eigen 的 MatrixXd 矩阵 在某个时刻我需要一个 3D 矩阵 由于 Eigen 没有三维矩阵类型 因为它仅针对线性代数进行了优化 因此我创建了一个 MatrixXd 类型的指针数组 Eigen MatrixXd
  • 单例模式和 std::unique_ptr

    std unique ptr唯一地控制它指向的对象 因此不使用引用计数 单例确保利用引用计数只能创建一个对象 那么会std unique ptr与单例执行相同 单例确保只有一个实例属于一种类型 A unique ptr确保只有一个智能指针到
  • 如何在服务器端按钮点击时关闭当前标签页?

    我尝试在确认后关闭当前选项卡 因此我将以下代码放在确认按钮的末尾 但选项卡没有关闭 string jScript ClientScript RegisterClientScriptBlock this GetType keyClientBl
  • AES 输出是否小于输入?

    我想加密一个字符串并将其嵌入到 URL 中 因此我想确保加密的输出不大于输入 AES 是可行的方法吗 不可能创建任何始终会创建比输入更小的输出的算法 但可以将任何输出反转回输入 如果您允许 不大于输入 那么基本上您只是在谈论同构算法alwa
  • 无法在内存位置找到异常源:cudaError_enum

    我正在尝试确定 Microsoft C 异常的来源 test fft exe 中 0x770ab9bc 处的第一次机会异常 Microsoft C 异常 内存位置 0x016cf234 处的 cudaError enum 我的构建环境是 I
  • 如何通过 JsonConvert.DeserializeObject 在动态 JSON 中使用 null 条件运算符

    我正在使用 Newtonsoft 反序列化已知的 JSON 对象并从中检索一些值 如果存在 关键在于对象结构可能会不断变化 因此我使用动态来遍历结构并检索值 由于对象结构不断变化 我使用 null 条件运算符来遍历 JSON 代码看起来像这
  • 如何在c的case语句中使用省略号?

    CASE expr no commas ELLIPSIS expr no commas 我在c的语法规则中看到了这样的规则 但是当我尝试重现它时 int test float i switch i case 1 3 printf hi 它失
  • C# 中的 strstr() 等效项

    我有两个byte 我想找到第二个的第一次出现byte 在第一个byte 或其中的一个范围 我不想使用字符串来提高效率 翻译第一个byte to a string会效率低下 基本上我相信就是这样strstr 在 C 中做 最好的方法是什么 这
  • C++ Streambuf 方法可以抛出异常吗?

    我正在尝试找到一种方法来获取读取或写入流的字符数 即使存在错误并且读 写结束时间较短 该方法也是可靠的 我正在做这样的事情 return stream rdbuf gt sputn buffer buffer size 但如果streamb
  • 矩阵到数组 C#

    这将是转换方阵的最有效方法 例如 1 2 3 4 5 6 7 8 9 into 1 2 3 4 5 6 7 8 9 in c 我在做 int array2D new int 1 2 3 4 5 6 7 8 9 int array1D new
  • 将 char[][] 转换为 char** 会导致段错误吗?

    好吧 我的 C 有点生疏了 但我想我应该用 C 来做我的下一个 小 项目 这样我就可以对其进行抛光 并且我已经有不到 20 行的段错误了 这是我的完整代码 define ROWS 4 define COLS 4 char main map
  • 使用 QtWebEngine 将 C++ 对象暴露给 Qt 中的 Javascript

    使用 QtWebkit 可以通过以下方式将 C 对象公开给 JavascriptQWebFrame addToJavaScriptWindowObject如中所述https stackoverflow com a 20685002 5959

随机推荐

  • 【JavaScript】2.1 高级语法特性

    在JavaScript的基础部分 我们已经学习了变量 数据类型 操作符 流程控制 函数 事件和DOM操作等基础知识 接下来 我们将学习一些JavaScript的高级语法特性 包括闭包 原型和原型链 作用域和作用域链 异步编程和Promise
  • 网站防盗链是什么

    随着互联网的快速发展 网站的安全问题越来越受到关注 其中 防盗链是许多网站面临的一个重要问题 本文将介绍网站防盗链的基本概念 原因以及如何采取措施进行保护 一 什么是网站防盗链 网站防盗链是指未经授权的网站通过技术手段获取并使用其他网站的资
  • 微信扫码登录修改二维码的样式

    默认是这个样子二维码都没有展示全 微信的了的 js 对象是这个样子 既然大家看到我这篇文章 想必里面的属性已经知道了 这里不做赘述 let href data text css base64 LmltcG93ZXJCb3ggLnFyY29k
  • python+requests接口自动化测试框架实例详解教程

    前段时间由于公司测试方向的转型 由原来的web页面功能测试转变成接口测试 之前大多都是手工进行 利用postman和jmeter进行的接口测试 后来 组内有人讲原先web自动化的测试框架移驾成接口的自动化框架 使用的是java语言 但对于一
  • MN316 OpenCPU丨Flash使用介绍

    在MN316 标准版SDK中 定义了操作模组内置flash接口 用户可操作空间为64KB 分为16个block 每个block大小为4KB 用户如有操作flash的需求 可调用相关接口 FOTA使用流程解析 以下流程图为使用 MN316 O
  • 聊聊刻意练习-构建心理表征

    这是鼎叔的第八十一篇原创文章 行业大牛和刚毕业的小白 都可以进来聊聊 欢迎关注本专栏和微信公众号 敏捷测试转型 星标收藏 大量原创思考文章陆续推出 本人新书 无测试组织 测试团队的敏捷转型 已出版 机械工业出版社 各大电商平台热销中 30万
  • enable_shared_from_this使用介绍

    文章目录 enable shared from this定义 使用场合 源码实现 注意 enable shared from this定义 定义于头文件 template lt class T gt class enable shared
  • HarmonyOS 振动效果开发指导

    Vibrator 开发概述 振动器模块服务最大化开放硬工最新马达器件能力 通过拓展原生马达服务实现振动与交互融合设计 打造细腻精致的一体化振动体验和差异化体验 提升用户交互效率和易用性 提升用户体验 增强品牌竞争力 运作机制 Vibrato
  • nginx服务无法启动。报错:[emerg] 8482#8482: still could not bind()

    安装nginx后发现nginx启动不起来 查看日志报错情况 tail 1000f var log nginx error log 2023 12 04 16 29 50 notice 8482 8482 try again to bind
  • PriorityQueue类

    PriorityQueue类 Java中的 PriorityQueue 是一个基于优先级堆的无界优先级队列 它是一个队列 可以按照元素的优先级顺序对元素进行排序 并且允许快速访问具有最高优先级的元素 它实现了 Queue 接口 继承了 Ab
  • Linux安装MariaDB数据库

    一句命令完成数据库的安装 环境 centos7 可以连接外网 一 安装MariaDB 命令 yum install mariadb mariadb server y root chensy yum install mariadb maria
  • 云原生之深入解析Kubernetes策略引擎对比:OPA/Gatekeeper与Kyverno

    一 前言 Kubernetes 策略 Kubernetes 的 Pod Security Policy 正如其名字所暗示的 仅是针对 Pod 工作的 是一种用来验证和控制 Pod 及其属性的机制 另外 PSP 只能屏蔽非法 Pod 的创建
  • Linux认证 | 国内常见的Linux认证有哪些

    国内常见的linux认证有哪些 许多打算从事或者正在从事IT事业的朋友 都对linux认证非常感兴趣 毕竟Linux作为目前 世界上最受认可的网络技术认证之一 一直深受IT行业的青睐 考取Linux认证 能够作为你进入行业的敲门砖 成为你
  • 软件测试/人工智能|Python 数据类型解析:探索编程世界的多样性

    数据类型是编程中不可或缺的基本概念 在 Python 中 有多种数据类型 每种都有其独特的特点和用途 本文将带你深入了解常见的 Python 数据类型及其实际应用 引言 在编程中 数据类型是对数据进行分类和组织的方式 Python 中有多种
  • 态势感知是什么

    在当今高度信息化的时代 信息安全风险已经成为企业 政府和个人的重要关注点 为了有效应对这些风险 态势感知成为了一种日益重要的能力 态势感知是一种基于环境的 动态 整体地洞悉安全风险的能力 是以安全大数据为基础 从全局视角提升对安全威胁的发现
  • 关于清空ant.design 中表单内容的方法

    关于清空ant design 中表单内容的方法 其实就两个方法具体怎么清除一个一个试试就知道了 表单有两个可能的属性 form formRef 可以用他们绑定两个用法在代码部分定义 form useRef form Form useForm
  • 算法题-简单系列-04-链表中倒数最后k个结点

    文章目录 1 题目 1 1 快慢指针 1 题目 输入一个长度为 n 的链表 设链表中的元素的值为 ai 返回该链表中倒数第k个节点 如果该链表长度小于k 请返回一个长度为 0 的链表 1 1 快慢指针 代码中的类名 方法名 参数名已经指定
  • 算法题-简单系列-07-判断一个链表是否为回文结构

    文章目录 1 题目 1 1 使用list集合判断 1 题目 给定一个链表 请判断该链表是否为回文结构 回文是指该字符串正序逆序完全一致 1 1 使用list集合判断 因为需要判断是否为回文结构 所以要比较头尾的数据 而链表无法随机查询数据
  • 296_C++_一个dialog对话框在执行exec向系统发送一个延后销毁事件时,另一个对话框立刻接管了上一个对话框的销毁事件,导致死UI

    1 根因分析 根因分析 当有新版本并且grade等级是2的时候 点击ptz的时候使用的是RSDialog WA DeleteOnClose属性默认是为true的 并且是栈上的变量 当关闭ptz的时候 diolog的exec结束会向系统发送延
  • C/C++STL学习[1]---顺序容器阐述、对比、选择vector,deque,list,forward_list,array,string

    文章目录 前言 1 顺序介绍 2 容器对比说明 3 容器选择 总结 前言 STL系列博客开篇 记录一下自己学C STL相关的心得 这篇博客主要是写顺序容器的类型以及各个容器之间的异同还有平时对容器使用的选择 1 顺序介绍 顺序容器表示这个容