C++ :vector的介绍和使用

vector学习时一定要学会查看reference

目录

前言

一、vector基本概念

1.1vector是什么?

1.2内存管理

二、vector的使用

2.1vector的构造

2.2vector iterator 的使用 

2.3vector 空间增长问题 

2.4vector的元素访问 

 2.5vector 增删查改

 总结



前言

在C++编程中,vector   是标准模板库(STL)中最常用的数据结构之一。它是一个封装了动态大小数组的序列容器,提供了灵活的内存管理方式和高效的元素访问机制。小编将介绍   vector   的基本特性、常用操作,帮助你更好地理解和掌握这一强大的工具。


一、vector基本概念

1.1vector是什么?

 vector是表示可变大小数组的序列容器。

  •  vector就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理
  • 与普通的数组相比,  vector   的大小可以动态变化,能够根据需要自动扩展或收缩。它通过模板实现,可以存储任意类型的元素,如整数、浮点数、字符串等。

1.2内存管理

 vector   在内部使用动态分配的内存来存储元素。当向   vector   中添加元素时,如果当前分配的内存不足以容纳新元素,  vector   会自动分配一块更大的内存,并将原有元素复制到新的内存中。这个过程称为“扩容”。扩容操作虽然在某些情况下会带来性能开销,但   vector   通过合理的内存分配策略(如每次扩容时将容量加倍)尽量减少了扩容的频率。


二、vector的使用

2.1vector的构造

 空容器构造函数 (默认构造函数)

构造一个空容器,没有元素。

#include <iostream>
#include <vector>
using namespace std;
int main ()
{// constructors used in the same order as described above:vector<int> first;                                // 无参构造return 0;
}

 填写构造函数

构造一个容器n元素。每个元素都是val(如果提供)。

int main ()
{std::vector<int> second (4,100);                       // 构造并初始化n个valreturn 0;
}

范围构造函数

构造一个包含与范围一样多的元素的容器[begin(),end()),与每个元素emplace-构造从该范围内的相应元素,以相同的顺序。

int main ()
{vector<int> second (4,100);                       // vector<int> third (second.begin(),second.end());  // 使用迭代器进行初始化构造return 0;
}

 (迭代器目前可以认为是指针)

 拷贝构造函数

int main ()
{vector<int> second (4,100);                       // four ints with value 100vector<int> third (second.begin(),second.end());  // iterating through secondvector<int> fourth (third);                       // 拷贝构造return 0;
}

 

2.2vector iterator 的使用 

 获取第一个数据位置的iterator/const_iterator:

获取最后一个数据的下一个位置的iterator/const_iterator

获取最后一个数据位置的reverse_iterator

 获取第一个数据前一个位置的reverse_iterator

 

 

 

 

2.3vector 空间增长问题 

 获取数据个数:

 

 获取容量大小:

capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。
这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。 

 

 判断是否为空:

 

 改变vector的size:

  • resize 指定的数据个数如果大于当前一段空间上的有效数据个数那么如果不指定数据会使用 0 作为有效数据追加在原数据序列后面,让有效字符个数变为指定字符个数,并且空间不够会扩容开空间,如果我们指定了数据则会使用我们指定的数据作为有效数据追加在原数据序列的后面
  • resize指定的数据个数如果小于当前有效数据个数,那么会将有效数据个数修改为指定数据个数,并且底层空间大小保持不变

  

 改变vector的capacity:

reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。

  • reserve 会一次性扩容开空间,如果你预想开的空间大于当前空间大小,那么开好的空间相较于你预期想要开的空间只多不少,reverse一般用于你提前已经预想好开多大空间了,这样使用reserve进行提前一次性开好空间提高效率,避免多次开空间
  • 如果你预想开的空间小于等于当前空间大小,那么当前空间大小保持不变
int main()
{
vector<int> v;
v.push_back(1);
v.push_back(1);
v.push_back(1);
v.push_back(1);
cout<<v.size();
cout<<v.capacity();
v.resize(10);
cout<<v.size();
v.reserve(10);
cout<<capacity();
return 0;
}

 

2.4vector的元素访问 

 

 operator[] :用于提供对容器或数组中元素的快速访问

与   at()   的区别:

operator[]  :

• 不进行边界检查。如果索引超出范围,行为是未定义的(可能导致程序崩溃)。

• 返回的是元素的引用,可以直接修改元素的值。

• 性能较高,因为它不进行额外的检查。

 at()  :

• 进行边界检查。如果索引超出范围,会抛出   std::out_of_range   异常。

• 返回的是元素的引用,也可以直接修改元素的值。

• 性能略低于   operator[]  ,因为需要进行额外的检查。

 

front:返回对第一个元素的引用向量。

 

 back:返回对最后一个元素的引用向量。

int main()
{int a[5] = { 1,2,3,4,5 };vector<int> v(a, a + 5);cout << v.at(1) << endl;cout << v.front() << endl;cout << v.back() << endl;return 0;
}

 

 2.5vector 增删查改

push_back:尾插

int main()
{
vector<int> v;
v.push_back(1);
v.push_back(1);
v.push_back(1);
v.push_back(1);
return 0;
}

 

pop_back:尾删

int main()
{
vector<int> v;
v.push_back(1);
v.push_back(1);
v.push_back(1);
v.push_back(1);
v.pop_back();return 0;
}

 

insert:在pos位置插入一个值/一个区间/n个值

int main()
{int a[5] = { 1,2,3,4,5 };vector<int> v(a, a + 5);// v=1,2,3,4,5v.insert(v.begin(), 5);//5,1,2,3,4,5for (int e : v){cout << e << ' ';}cout << endl;v.insert(v.begin(), 5 , 1);//1,1,1,1,1,5,1,2,3,4,5for (int e : v){cout << e << ' ';}cout << endl;vector<int> v0(3, 6);v.insert(v.end(), v0.begin(),v0.end());//1,1,1,1,1,5,1,2,3,4,5,6,6,6for (auto e : v){cout << e << ' ';}cout << endl;return 0;
}

 

assign:将要传入数据的对象的原有的数据清空,再去分派数据

int main()
{string s("hello world");vector<char> v;v.assign(s.begin(), s.end());for (char e : v){cout << e;//"hello world"}cout << endl;v.assign(6,6);for (char e : v){cout << e << ' ';//6,6,6,6,6,6}cout << endl;return 0;
}

 

erase:删除一个迭代器位置上的值并且返回这个删除的迭代器的下一个数据的位置的迭代器

注意:由于当前迭代器位置的值已经被删除,所以当前位置的迭代器位置的值的下一个位置的值会向前顶替当前位置的值,那么下一个数据的值就成了当前位置上的数据,返回的是当前位置的迭代器,但当前位置的迭代器上的值改变了

 

 swap:交换两个vector的数据空间

int main()
{vector<int> v1(6, 1);vector<int> v2(6, 0);cout << "v1的数据序列为:";//1,1,1,1,1,1for (auto e : v1){cout << e << ' ';}cout << endl;cout << "v2的数据序列为:";//0,0,0,0,0,0for (auto e : v2){cout << e << ' ';}cout << endl << endl;v1.swap(v2);//v1和v2交换了数据空间cout << "v1的数据序列为:";for (auto e : v1){cout << e << ' ';//0,0,0,0,0,0}cout << endl;cout << "v2的数据序列为:";for (auto e : v2){cout << e << ' ';//1,1,1,1,1,1}cout << endl;return 0;
}

 

clear:清空vector类模板实例化出的对象的全部数据

int main()
{vector<int> v1(6, 1);v1.clear();//v1被清空return 0;
}

 总结

vector的使用场景:

  •  动态数组需求当需要一个大小可动态变化的数组时,  vector   是理想的选择。它能够根据元素的添加和删除自动调整内存分配,避免了手动管理内存的复杂性。
  • 高效的随机访问  vector   支持高效的随机访问,通过索引可以快速获取任意位置的元素。这使得它在需要频繁随机访问元素的场景中非常高效。
  • 与其他STL算法配合  vector   作为STL容器,能够无缝地与STL算法(如排序、查找等)配合使用,从而实现复杂的数据处理逻辑。

Vector的注意事项:

  • 虽然   vector   的扩容策略尽量减少了扩容的频率,但在某些高频插入的场景中,扩容仍然可能带来一定的性能开销。如果事先知道   vector   的大致大小,可以通过   reserve()   方法预先分配足够的内存,从而避免多次扩容。
  • 迭代器失效在对   vector   进行插入或删除操作时,可能会导致迭代器失效。特别是当插入或删除操作导致内存扩容或收缩时,所有迭代器都会失效。因此,在使用迭代器时需要注意迭代器的有效性。

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

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

相关文章

iOS OC 图片压缩

纯代码,不废话,欢迎copy使用,记得点赞 +(NSData *)imageData:(UIImage *)image maxSize:(int)maxSize{ // 设置最大文件大小(200KB) NSLog(@"执行压缩方案 期望压缩目标%dk",maxSize); return [self compressImage:image toMaxSize:maxSize]; } // 主压缩方…

如何更改 SQLserver 数据库存储的位置 想从C盘换到D盘

在 SQL Server 中更改数据库存储位置&#xff08;从 C 盘迁移到 D 盘&#xff09;需要通过以下步骤完成&#xff1a;1. 确定数据库文件的当前位置首先查询数据库文件的当前路径&#xff1a;sqlSELECT name, physical_name AS current_location FROM sys.master_files WHERE dat…

【unitrix】 6.8 加一运算(add_one.rs)

一、源码 这是一个使用 Rust 类型系统实现二进制数加一操作的代码。 use crate::number::{O, I, B, Null, Bit, NormalizeIf};/// 类型级加一操作 trait /// /// 为二进制数类型实现加一操作&#xff0c;返回新的类型 pub trait AddOne {/// 加一操作的结果类型type Output;//…

国内Ubuntu访问不了github、 huggingface等

各位小伙伴们&#xff0c;大家好呀。 大家是不是经常遇到访问不了github、huggingface的情况呀。 在Ubuntu中可以这样做。 访问这个网站网站测速-Ping检测-Trace查询-Dig查询-路由跟踪查询-tools.ipip.net&#xff0c; 对于github.com&#xff0c;在这个网站输入github.com…

「Java EE开发指南」如何用MyEclipse创建企业应用项目?(一)

由于有了项目模型和管理工具&#xff0c;现在可以创建Java EE企业应用程序。在本文中您将了解到&#xff1a; 企业应用项目模型项目组织、依赖关系和类解析 该特性在MyEclipse中可用。 MyEclipse v2025.1离线版下载 1. 企业应用项目模型 MyEclipse提供了一个企业应用程序项…

ubuntu 22.04 pam 模块设置用户登录失败锁定

1、ubuntu 22.04 配置方法 /etc/pam.d/common-auth 加到如下行后 # auth [success1 defaultignore] pam_unix.so nullok # 添加如下内容 auth [defaultdie] pam_faillock.so authfail auth sufficient pam_faillock.so authsucc/etc/pam.d/common…

Linux 定时任务全解析:atd 与 crond 的区别及实战案例(含日志备份 + 时间写入)

1. atd 和 crond 两个任务管理程序的区别atd&#xff1a;用于执行一次性的定时任务&#xff0c;即设置任务在某个特定的时间点仅执行一次 &#xff0c;适合处理不需要重复执行的定时操作&#xff0c;比如在未来某个确切时间执行一个脚本、发送一份文件等场景。crond&#xff1a…

iOS加固工具有哪些?项目场景下的组合策略与实战指南

在如今的iOS项目中&#xff0c;“加固”不仅是单一手段&#xff0c;更是多工具协同应用的过程。不同项目场景对安全要求的侧重点不同&#xff0c;需要针对性地组合加固工具&#xff0c;才能最大化兼顾安全性、兼容性与效率。 本文将从常见项目场景出发&#xff0c;分析当下市面…

Xilinx Zynq:一款适用于软件定义无线电的现代片上系统

摘要——软件定义无线电可以在通用处理器 (CPU) 上实现&#xff0c;例如基于 PC 的处理器。处理器具有高度灵活性&#xff1a;它不仅可以用来处理数据样本&#xff0c;还可以控制接收器功能、显示瀑布图或运行解调软件。然而&#xff0c;由于处理速度相对较慢&#xff0c;处理器…

接口黑洞?破!安全堡垒?筑!冰火炼狱?战!MES7114W终极掌控

在工业4.0加速推进的时代&#xff0c;设备互联正面临三大关键挑战&#xff1a;多协议接口的“通信割裂”、极端环境的严苛考验&#xff0c;以及高危场景下的安全红线。在矿山井下、冶金车间、化工厂区等恶劣环境中&#xff0c;传统有线方案往往受限于高成本布线、维护困难和环境…

深入理解进程地址空间:虚拟内存与进程独立性

目录 引言 虚拟地址空间的本质 关键观察 进程地址空间布局 虚拟内存管理&#xff1a;mm_struct 虚拟内存的优势 总结 引言 在操作系统中&#xff0c;每个进程都运行在自己的独立区域中&#xff0c;这个区域就是​​进程地址空间​​。今天我们就来探讨这个看似真实实则虚…

Apache ActiveMQ 任意文件写入漏洞(CVE-2016-3088)复现利用

漏洞原理 Apache ActiveMQ是Apache软件基金会所研发的开放源代码消息中间件&#xff0c;由于ActiveMQ是一个纯Java程序&#xff0c;因此只需要操作系统支持Java虚拟机&#xff0c;ActiveMQ便可执行 本漏洞出现在fileserver应用中&#xff0c;漏洞原理其实非常简单&#xff0c…

谷歌地球与ArcGIS Pro查看三维地形

&#xff08;1&#xff09;Google Earth Web端 通过网站&#xff1a;https://earth.google.com/&#xff0c;进入谷歌地球Web端&#xff0c;可以查看历史影像、三维地形数据、导入kml文件等。 &#xff08;2&#xff09;ArcGIS Pro查看三维场景 加载3D地形数据&#xff0c;转…

Day06_C语言网络编程20250718

01.思维导图1 什么是 modbus他是一个在工控领域非常好用的通信写 modbus协议本质上是一个 基于 tcp 协议二次封装的一个协议 什么叫做基于tcp二次封装的协议&#xff1a;我们自己写的pack_t(无论静态还是动态)&#xff0c;都是属于二次封装的协议modbus协议是一种 “主从问答式…

web开发-HTML

web开发——HTML 学习目标&#xff1a;学习HTML的基础&#xff0c;学会get和post方法区别 一、HTMLHTML是什么&#xff1f; 前端网页界面开发语言。开发工具 PyCharm、vscodePyCharm个性化设置&#xff08;字体和背景颜色&#xff09; File - setting - appearance - theme&…

主流编程语言全景图:从Python到Rust的深度解析

2024年编程语言生态报告显示&#xff0c;全球开发者使用的语言数量已达260&#xff0c;但真正主导行业的不到20种。本文带你穿透技术迷雾&#xff0c;掌握8大核心语言的本质差异。一、选择编程语言的黄金标准图表代码二、八大主流语言对比解析1. Python - 通用胶水语言特性&…

若依框架下前后端分离项目交互流程详解

在企业级前后端分离项目开发中&#xff08;如若依RuoYi&#xff09;&#xff0c;前端与后端的数据交互、安全认证、权限校验、响应处理都是必须关注的重点。本文将以“课程管理列表查询”为例&#xff0c;详细梳理整个交互流程&#xff0c;每一步均有解析说明和典型代码&#x…

cartorgapher的编译与运行

目录 cartorgapher的编译环境 cartorgapher的编译 cartographer的运行 参数的详解与调参总结 降低延迟与减小计算量 cartorgapher的编译环境 系统环境 推荐在ubuntu16.04或者18.04上进行编译 推荐使用刚装好的ubuntu系统 将ubuntu的软件源设置成清华的或者其他的中国境内的…

浅谈车载电控和机器人一体化关节电控区别和联系

类别车载电机关节电机&#xff08;伺服电机)电机PMSM 有轴 永磁体内嵌IPMPMSM&BLDC 永磁体表贴 SPM&#xff0c;转速不高&#xff0c;减少体积 关节和推杆用无框力矩电机&#xff1a;只有定子和转子&#xff0c;无轴&#xff0c;无外壳和端盖&#xff0c;便于和编码器减速器…

【数据结构】堆(下)+ 二叉树

上期回顾&#xff1a;【数据结构】树&#xff08;堆&#xff09;上 一.堆的应用 1.1堆排序&#xff08;向下调整在上一期&#xff09; 向上调整算法建堆&#xff1a; 首先先回顾一下向上调整算法 void AdjustUP(HPDataType* arr, int child) {int parent (child - 1) / 2…