[C++ STL] vector 详解
标题:[C++ STL] vector 详解
@水墨不写bug
目录
一、背景
二、vector简介
三、vector的接口介绍
(1)默认成员函数接口
i,构造函数(constructor)
ii,析构函数(destructor)
iii,拷贝构造
iv,赋值重载
(2)迭代器接口
(3)容量接口
i,size()
ii,max_size()
iii,resize()
iv,capacity()
v,empty()
vi,reserve()
vii,shrink_to_fit()
(4)元素访问接口
i,operator[]
ii,at()
iii,front()
iv,back()
(5)修改接口
i,push_back()
ii,pop_back()
iii,insert()
iv,erase()
v,swap()
vi,clear()
正文开始:
一、背景
我们在学习C语言时就渴望过一种可以自动扩容的数组。尽管C99标准引入了变长数组:
变长数组
变长数组是C99标准新增的特性,它允许在运行时动态地指定数组的长度。与传统的静态数组不同,变长数组的长度可以在程序运行时确定,而不是在编译时确定。
但是变长数组不是真正的可以随意扩容的容器:因为在运行时,变长数组的长度只能确定一次。一旦变长数组的长度确定,就无法再次改变了!
这也是C语言的痛点,为了实现随意扩容的功能,我们可以实现一个动态顺序表(Dynamic Sequence List):
可变长的顺序表(Dynamic Sequence List)
是一种能够动态调整存储空间大小的顺序表。它的大小是可以根据需要进行动态扩展或缩小的,不需要在初始化时指定固定的容量。
实现可变长顺序表的方式有多种,其中一种常见的方式是使用动态数组。动态数组是在内存中分配一块连续的存储空间来存储元素,当元素个数超过当前分配的空间大小时,会重新分配更大的空间,并将原有的元素复制到新的空间中,然后释放原有的空间。
但是每次在使用前,都要实现一个顺序表太麻烦了,用C语言实现一个顺序表动辄就几百行,这样不断重复“造轮子”的行为导致开发十分低效。在这样的背景下,C++中引入了STL:
STL(Standard Template Library)
是C++标准库中的一个重要组成部分,提供了一系列的模板类和算法,用于处理常见的数据结构和算法问题。STL包括了容器(Containers)、迭代器(Iterators)、算法(Algorithms)和函数对象(Function Objects)等组件,提供了丰富的数据结构和算法操作。
其中的容器,就是帮助我们解决问题的组件。本文讲解的vector就是容器中的非常常用常见的一个。
二、vector简介
vector是STL中的一个容器,实现了动态数组的功能。它可以存储任意类型的元素,并提供了一系列的操作函数,如插入、删除、访问等。
vector的特点包括:
- 动态大小:vector的大小可以根据需要进行动态调整,可以随时增加或减少元素的数量。
- 连续存储:vector的元素在内存中是连续存储的,可以通过下标快速访问元素。
- 头部插入删除效率较低:由于在头部插入或删除元素时需要进行大块内存的复制或移动,导致效率较低。
- 随机访问效率高:由于元素的连续存储,可以通过下标直接访问任意位置的元素。
三、vector的接口介绍
由于在实际应用中,vector的一些接口并不常用,所以本介绍尽量在完整的基础上简洁。
(1)默认成员函数接口
在正式开始介绍之前,我们先认识一个之前已经见过的关键字:
explicit:
在C++中,
explicit
是一个关键字,用于防止类构造函数进行隐式类型转换。当你有一个类,并且这个类有一个可以从其他类型隐式转换的构造函数时,你可能会在无意中创建该类的对象,而不是你原本想要的。使用explicit
关键字可以确保这种转换是显式的,从而避免潜在的错误。class MyClass { public: explicit MyClass(int value) { // ... } }; void foo(MyClass obj) { // ... } int main() { // 下面的代码会因为 MyClass 的构造函数是 explicit 的而编译失败 // foo(42); // 错误:无法从 'int' 转换为 'MyClass' // 你必须显式地创建一个 MyClass 对象 foo(MyClass(42)); // 正确 return 0; }
这样就可以开始介绍了。
i,构造函数(constructor)
default (1) explicit vector (const allocator_type& alloc = allocator_type());默认构造,创建一个没有数据的vector。
vector<int> v;
fill (2) explicit vector (size_type n);vector (size_type n, const value_type& val,const allocator_type& alloc = allocator_type());创建一个有n个元素的vector,每个元素初始化为提供的val的值。(如果没有提供val,则默认初始化为0)
vector<int> v(10);cout<<v[6]<<endl;//输出0
range (3) template <class InputIterator>vector (InputIterator first, InputIterator last,const allocator_type& alloc = allocator_type());迭代器初始化,根据提供的容器迭代器范围内的数据来初始化vector。
list<int> l = { 1,2,5,73 }; vector<int> v(l.begin(), l.end()); //v的数据也是1,2,5,73
ii,析构函数(destructor)
~vector();销毁容器对象。(编译器会自动调用)
iii,拷贝构造
copy | vector (const vector& x); vector (const vector& x, const allocator_type& alloc); 用x中每个元素的的值按相同顺序构造一个vector。 |
---|
iv,赋值重载
copy (1) | vector& operator= (const vector& x); 对“=”操作符重载。 |
---|
noexcept:
noexcept
是 C++11 引入的一个关键字,用于指定某个函数或函数模板是否抛出异常。如果一个函数被声明为noexcept
,那么它承诺在执行过程中不会抛出任何类型的异常。
(2)迭代器接口
iterator begin() noexcept; const_iterator begin() const noexcept;返回容器指向第一个元素的迭代器,普通对象调用普通的,const对象调用const的函数。
(由于次类型函数仅仅是返回一个迭代器类型的变量,不会产生抛异常的现象;同时一个函数被声明为
noexcept
,那么编译器可能会生成更高效的代码,因为它不需要为这个函数准备异常处理逻辑。所以为了提高效率,加上了noexcept
)
iterator end() noexcept; const_iterator end() const noexcept;返回容器指向最后一个元素的下一个位置的迭代器,普通对象调用普通的,const对象调用const的函数。
reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept;返回容器指向最后一个元素的迭代器,普通对象调用普通的,const对象调用const的函数。
reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept;返回容器指向第一个元素的前一个位置的迭代器,普通对象调用普通的,const对象调用const的函数。
const_iterator cbegin() const noexcept;const_iterator cend() const noexcept;const_reverse_iterator crbegin() const noexcept;const_reverse_iterator crend() const noexcept;这些是STL中提供的上面迭代器的const版本。但其实begin已经有重载一个const版本了,所以const迭代器也可以接受begin(const重载)的返回值。于是这4个接口即使不存在,也不会影响vector的const迭代器的正常使用。
(3)容量接口
i,size()
size_type size() const noexcept;返回vector中元素的个数。这是vector中保存的实际对象的数量,不一定等于它的存储容量。
vector<int> v={1,2,3}; vector<int>::const_iterator it = v.cbegin(); v.push_back(4); v.push_back(5); v.push_back(6); v.push_back(7); v.push_back(8); v.push_back(9); v.push_back(10); v.push_back(11); v.push_back(12); v.push_back(13); v.push_back(14); cout << v.size() << ":" << v.capacity()<<endl;
ii,max_size()
size_type max_size() const noexcept;返回vector所能容纳的最大元素数。由于已知的系统或库实现限制,这是容器可以达到的最大理论大小,但是容器不能保证能够达到这个大小。所以max_size()没有实际的参考意义。
iii,resize()
void resize (size_type n); void resize (size_type n, const value_type& val);传入一个参数n,n是指定的size大小:
如果n小于size,则缩容到n;
如果n等于size,不操作;
如果n大于size:
如果n小于等于capacity,不扩容,将size增大到n,并用指定的val初始化新扩容的元素。(如果没有指定,默认用0初始化)
如果n大于capacity,需要扩容,扩容的规模 根据编译器的处理而定 ,扩容之后将size增大到n,并用指定的val初始化新扩容的元素。(如果没有指定,默认用0初始化)
iv,capacity()
size_type capacity() const noexcept;返回当前为vector分配的存储空间大小,以元素表示。
v,empty()
bool empty() const noexcept;返回向量是否为空(即它的大小是否为0)。
为空返回真,非空返回假。
vi,reserve()
void reserve (size_type n);要求vector容器容量至少足以容纳n个元素。
如果n大于当前的vector容量,则该函数使容器重新分配其存储空间,将其容量增加到n(或更大)。
在所有其他情况下,函数调用不会导致重新分配,向量容量也不会受到影响。这个函数对vector的size没有影响,也不能改变vector的元素。
vii,shrink_to_fit()
void shrink_to_fit();请求容器减少其容量以适合其大小。
(4)元素访问接口
i,operator[]
reference operator[] (size_type n); const_reference operator[] (size_type n) const;返回对vector容器中位置n的元素的引用。普通对象调用普通函数,const对象调用调用const函数,并且const函数的函数返回的引用不能被修改。
类似的成员函数vector::at()具有与此操作符函数相同的行为,除了vector::at是绑定检查的,并且如果请求的位置超出范围,则通过抛出out_of_range异常来发出信号。
可移植强的程序 不应该使用超出范围的参数n调用此函数,因为这会导致未定义的行为。
ii,at()
reference at (size_type n); const_reference at (size_type n) const;返回对vector中位置n的元素的引用。
该函数自动检查n是否在vector中有效元素的范围内,如果不在,则抛出out_of_range异常(即,如果n大于或等于其大小)。这与成员operator[]相反,operator[]不检查边界。
iii,front()
reference front(); const_reference front() const;返回对vector中第一个元素的引用。
普通对象调用普通函数,const对象调用调用const函数,并且const函数的函数返回的引用不能被修改。
与返回指向同一元素的迭代器的成员vector::begin不同,此函数返回直接引用。在空容器上调用此函数会导致未定义行为。
iv,back()
reference back(); const_reference back() const;返回对vector中最后一个元素的引用。
普通对象调用普通函数,const对象调用调用const函数,并且const函数的函数返回的引用不能被修改。
与成员vector::end不同,后者返回经过该元素的迭代器,此函数返回直接引用。在空容器上调用此函数会导致未定义行为。
(5)修改接口
i,push_back()
void push_back (const value_type& val); void push_back (value_type&& val);在vector当前最后一个元素的末尾添加一个新元素。val的内容被复制(或移动)到新元素中。
这将容器大小增加了1,当且仅当新向量大小超过当前向量容量时,会自动重新分配已分配的存储空间。
ii,pop_back()
void pop_back();移除vector中的最后一个元素,有效地将容器大小减小1。
iii,insert()
single element (1) | iterator insert (const_iterator position, const value_type& val); 在下标为position位置的迭代器插入一个元素val。 |
---|---|
fill (2) | iterator insert (const_iterator position, size_type n, const value_type& val); 在下标为position位置的迭代器插入n个元素val。 |
range (3) | template <class InputIterator> iterator insert (const_iterator position, InputIterator first, InputIterator last); 迭代器区间初始化,在下标为position位置的迭代器插入一个迭代器区间内的值。 |
iv,erase()
iterator erase (const_iterator position); iterator erase (const_iterator first, const_iterator last);从vector对象中移除单个元素(position)或一段元素([first,last))。这有效地减少了容器的大小,通过删除元素的数量,这些元素被销毁。
由于vector使用数组作为其底层存储,因此删除位于vector末端以外位置的元素会导致容器将擦除段后的所有元素重新移动到新位置。
与其他类型的序列容器(如list或forward_list)所执行的相同操作相比,这通常是一个效率低下的操作。
v,swap()
void swap (vector& x);用x的内容交换容器的内容,x是另一个相同类型的vector对象。大小可能不同。在调用this成员函数之后,this容器中的元素是调用之前在x中的元素,而x的元素是在this容器中的元素。
所有迭代器、引用和指针对于交换后的对象仍然有效。注意,存在一个具有相同名称的非成员函数,swap,用行为类似于该成员函数的优化重载该算法。
vi,clear()
void clear() noexcept;从vector中移除所有元素(这些元素被销毁),使容器的大小为0。
完~
未经作者同意禁止转载
相关文章:
[C++ STL] vector 详解
标题:[C STL] vector 详解 水墨不写bug 目录 一、背景 二、vector简介 三、vector的接口介绍 (1)默认成员函数接口 i,构造函数(constructor) ii,析构函数(destructor࿰…...
PHP简约轻型聊天室留言源码
无名轻聊是一款phptxt的轻型聊天室。 无名轻聊特点: 自适应电脑/手机 数据使用txt存放,默认显示近50条聊天记录 采用jqueryajax轮询方式,适合小型聊天环境。 访问地址加?zhi进入管理模式,发送 clear 清空聊天记录。 修改在…...
代码随想录算法训练营day23|669.修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树
669.修剪二叉搜索树 这道题目需要考虑当前节点是否在[low,high]之间, 因为是平衡二叉树, 所以当当前节点值小于low时,那么其左节点肯定更小,因此删除该节点的方式是给root节点返回其右节点的递归,注意:这里…...
实时通信websocket和sse
microsoft/fetch-event-source是一个JavaScript库,用于处理服务器发送的事件(Server-Sent Events,简称SSE)。它提供了一个简单易用的API,使得客户端可以与服务器进行实时通信。这个库主要用于浏览器环境 安装依赖npm i…...
(超详细)基于动态顺序表实现简单的通讯录项目
前言: 我们在上一章节用c语言实现了线性表中的的动态顺序表,那么顺序表就只是顺序表吗?当然不是,使用顺序表结构可以实现很多项目,许多项目的数据结构都会用到顺序表,本章节我们就要使用顺序表实现一个简易…...
修改SubVI的LabVIEW默认搜索路径
在启动顶级VI后,LabVIEW可能会遇到找不到subVI的情况。这通常是由于subVI的路径发生了变化或没有被正确配置。 LabVIEW默认搜索路径 默认情况下,LabVIEW会按以下顺序搜索文件位置(*表示LabVIEW将搜索子目录): <t…...
基于python深度学习的CNN图像识别鲜花-含数据集+pyqt界面
代码下载: https://download.csdn.net/download/qq_34904125/89383615 本代码是基于python pytorch环境安装的。 下载本代码后,有个requirement.txt文本,里面介绍了如何安装环境,环境需要自行配置。 或可直接参考下面博文进行…...
第九站:Java黑——安全编码的坚固防线(第②篇)
4. 验证和过滤输入数据示例:使用Apache Commons Lang 对输入数据进行验证和过滤是防止多种安全漏洞的关键步骤,包括但不限于SQL注入和命令注入。Apache Commons Lang库提供了一些实用方法来帮助进行字符串操作和验证。以下是一个简单的示例,…...
如何优雅的删除正式环境中的大表
引起 MySQL 数据库性能抖动的原因有很多,比如大事务、定时批量查询等,而这些原因我们一般都会注意到。但是,有一个引起性能抖动的原因却经常被我们忽视,那就是在生产环境删除无用的大表,即 DROP TABLE。 一、为什么要 DROP TABLE? 生产环境中,为什么要 DROP TABLE?相…...
Vulnhub-DC-1,7
靶机IP:192.168.20.141 kaliIP:192.168.20.128 网络有问题的可以看下搭建Vulnhub靶机网络问题(获取不到IP) 前言 1和7都是Drupal的网站,只写了7,包含1的知识点 信息收集 用nmap扫描端口及版本号 进入主页查看作者给的提示,不是暴力破解的…...
使用MySQL全文索引实现高效搜索功能
MySQL全文索引是MySQL提供的一种高效的搜索功能,可以快速地搜索文本内容。全文索引可以用于搜索大量文本数据,通常应用在文章、博客、论坛等需要搜索的场景中。 什么是MySQL全文索引 MySQL全文索引是一种用于快速搜索文本内容的索引技术。它可以在存储和…...
数据结构学习笔记-图
1.图的存储 (1)邻接矩阵法 #define MaxVertexNum 100 //顶点数目的最大值 typedef struct{char Vex[MaxVertexNum]; //顶点表int Edge[MaxVertexNum][MaxVertexNum]; //邻接矩阵表,边表int vexnum,arcnum; //图的当前顶点数和边…...
【归并排序】| 详解归并排序核心代码之合并两个有序数组 力扣88
🎗️ 主页:小夜时雨 🎗️专栏:动态规划 🎗️如何活着,是我找寻的方向 目录 1. 题目解析2. 代码 1. 题目解析 题目链接: https://leetcode.cn/problems/merge-sorted-array/description/ 本道题是归并排序的…...
51单片机STC89C52RC——2.3 两个独立按键模拟控制LED流水灯方向
目的 按下K1键LED流水向左移动 按下K2键LED流水向右移动 一,STC单片机模块 二,独立按键 2.1 独立按键位置 2.2 独立按键电路图 这里要注意一个设计的bug P3_1 引脚对应是K1 P3_0 引脚对应是K2 要实现按一下点亮、再按一下熄灭,我们就需…...
Neo4j连接
终端输入: neo4j console 浏览器访问:http://localhost:7474/ 输入用户名和密码:neo4j, 梦想密码(首次neo4j) 代码连接用新的服务器地址: g Graph(neo4j://localhost:7687, auth(neo4j, ))…...
List 列表
文章目录 一、什么是 List 列表1.1 创建 List 列表的方式1.2 列表的新增函数方法1.3 列表的删除函数方法1.4 修改列表数据的方法1.5 列表的查询函数方法1.6 列表的排序和反序1.7 列表的复制 一、什么是 List 列表 List 列表:该数据类型定义的变量可以理解为是一个数…...
nginx ws长连接配置
nginx ws长连接配置 http根节点下配上 map $http_upgrade $connection_upgrade {default upgrade; close;}如下: server服务节点下,后端接口的代理配置 proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connec…...
Windows下访问wsl的数据
Windows下访问wsl的数据 有些人感受到的是雨,而很多人感受到的只有淋湿。 Windows下的wsl说实话还是挺不错的,对于开发而言,效果相当的可以。 比如在某个文件夹,Windows编辑好代码后,直接右键打开wsl,就可…...
机器学习笔记 - 用于3D数据分类、分割的Point Net简述
一、简述 在本文中,我们将了解Point Net,目前,处理图像数据的方法有很多。从传统的计算机视觉方法到使用卷积神经网络到Transformer方法,几乎任何 2D 图像应用都会有某种现有的方法。然而,当涉及到 3D 数据时,现成的工具和方法并不那么丰富。3D 空间中一个工具就是Point …...
vscode 连接 GitHub
目录 vscode连接github一、解决 github 登录问题二、通过 SSH 连接 github1、只有一个 git 账号2、切换 git 账号3、在两个账号之间切换 vscode 连接 gitee一、通过 HTTPS 连接二、通过 SSH 连接 vscode连接github 在 vscode 中首次使用 git push 命令时会要求输入 github 账户…...
集合java
1.集合 ArrayList 集合和数组的优势对比: 长度可变 添加数据的时候不需要考虑索引,默认将数据添加到末尾 package com.itheima;import java.util.ArrayList;/*public boolean add(要添加的元素) | 将指定的元素追加到此集合的末尾 | | p…...
智能体(Agent)实战——从gpts到auto gen
一.GPTs 智能体以大模型作为大脑,同时配备技能,使其能够完成具体的任务。同时,为了应用于垂直领域,我们需要为大模型定义一个角色,并构建知识库。最后,定义完整的流程,使其完成整个任务。以组会…...
PyTorch 张量数据类型
【数据类型】Python 与 PyTorch 常见数据类型对应: 用 a.type() 获取数据类型,用 isinstance(a, 目标类型) 进行类型合法化检测 >>> import torch >>> a torch.randn(2,3) >>> a tensor([[-1.7818, -0.2472, -2.0684],[ 0.…...
奇思妙想-可以通过图片闻见味道的设计
奇思妙想-可以通过图片闻见味道的设计 偷闲半日享清闲,炭火烧烤乐无边。肉串飘香引客至,笑语欢声绕云间。人生难得几回醉,且把烦恼抛九天。今宵共饮开怀酒,改日再战新篇章。周四的傍晚,难得的闲暇时光让我与几位挚友相…...
装饰者模式(设计模式)
装饰模式就是对一个类进行装饰,增强其方法行为,在装饰模式中,作为原来的这个类使用者还不应该感受到装饰前与装饰后有什么不同,否则就破坏了原有类的结构了,所以装饰器模式要做到对被装饰类的使用者透明,这…...
ADB调试命令大全
目录 前言命令大全1.显示当前运行的全部模拟器:adb devices2.启动ADB: adb start-server3.停止ADB: adb kill-server4.安装应用程序: adb install -r [apk文件]5.卸载应用程序: adb uninstall [packagename]6.将手机设备中的文件copy到本地计…...
查看npm版本异常,更新nvm版本解决问题
首先说说遇见的问题,基本上把nvm,npm的坑都排了一遍 nvm版本导致npm install报错 Unexpected token ‘.‘install和查看node版本都正确,结果查看npm版本时候报错 首先就是降低node版本… 可以说基本没用,如果要降低版本的话&…...
计算机行业
计算机行业环境分析 2022.01.12 计算机行业环境分析 计算机专业就业前景 随着科技的进步和信息事业的发展,尤其是计算机技术的发展与网络应用的逐渐普及。计算机已成为人们工作和生活中不可缺少的东西。IT行业迅猛发展,就业工作岗位也比比皆是。在最近…...
各种机器学习算法的应用场景分别是什么(比如朴素贝叶斯、决策树、K 近邻、SVM、逻辑回归最大熵模型)?
2023简直被人工智能相关话题席卷的一年。关于机器学习算法的热度,也再次飙升,网络上一些分享已经比较老了。那么今天借着查询和学习的机会,我也来浅浅分享下目前各种机器学习算法及其应用场景。 为了方便非专业的朋友阅读,我会从算…...
SQLite JDBC驱动程序
SQLite JDBC驱动程序下载地址: 下载地址...
成都企业网站建设/石家庄新闻网
创建使用 Web 部件的简单页面 不需要执行任何操作即可启用 Web 部件个性化设置;默认情况下为 Web 部件控件集启用该功能。当第一次在某个站点上运行 Web 部件页时,ASP.NET 将设置一个默认的个性化设置提供程序来存储用户个性化设置。默认提供程序使用在站…...
乡村文化建设网站栏目设置/企业网站建设公司
本文章是❤️力扣 (LeetCode)❤️的内容,该专栏还有多篇优质内容在等待你观看,现在点击右上角点击这个————🚀订阅专栏🚀 🔆坚持刷算法 💎每天进步一点点 🚀冲冲冲冲冲冲冲冲冲冲 Ǵ…...
装修网站建设/百度网站快速优化
https://community.fs.com/blog/do-you-know-the-differences-between-hubs-switches-and-routers.html 介绍hub,switch,router,有动图,很形象 http://blog.csdn.net/wuruixn/article/details/8350773 介绍交换机和路由器 http://…...
自己做的网站如何让别的网可以查看/温州seo优化
没怎么用过这个新特性。事实上也不算新啦,试试吧,如今静态类的继承非常方便了 <?php class A {protected static $def 123456;public static function test() {echo get_class(new static);}public static function test2() {echo static::$def;} }…...
营销型网站设计建设公司/福州网站建设策划
Android设计模式系列(10)--SDK源码之原型模式 Android设计模式系列(9)--SDK源码之适配器模式 Android设计模式系列(8)--SDK源码之工厂方法模式 Android设计模式系列(7)--SDK源码之命令模式 Android设计模式系列(6)--SDK源码之享元模式 Android设计模式系列(5)--SDK源码之备忘录…...
济宁网站建设方面/个人网站制作模板
XAML(eXtensible Application Markup Language,可扩展应用程序标记语言)是一种声明式的编程语言,遵循XML的语法。WPF使用XAML来设计UI具有易用性、高效性等特点。易用性主要表现在设计师在不需懂逻辑代码的情况下就可以使用Expres…...