【C++】vector容器的基本使用
一、vector是什么
vector是STL第一个正式的容器,它的底层其实就是动态数组,插入数据时当容量满了会自动扩容,它和string差不多,不同的之处之一在于vector本身是一个模板,它这个容器中可以存放各种各样的类型的数据,而string已经是模板实例化之后的结果。

vector类模板的第一个参数是T,其实就是你要放进容器中数据的类型,第二个参数我们暂且不管,它是一个空间配置器,主要是提高效率的,我们在实例化时暂且不传第二个参数,用它的默认缺省值,我们暂且只传第一个参数即可。
在本篇中涉及到allocator空间配置器的我们暂且不用管,可以先忽略。
vector大多数接口和string的功能用法上没有什么太大的区别,这篇文章不会细讲,所以建议大家先去看一下这篇文章 -> string类的基本实现
二、基本使用
1、构造函数

C++98版本下有4个构造函数,我们这里只说C++98,不谈论其它版本。
我们来看一下它的使用:
void test_vector1()
{vector<int> v1; //(1)默认构造vector<int> v2(10,1); //(2)带参构造,int类型的10个1vector<int> v3(v2.begin(),v2.end()); //(3)迭代器区间构造vector<int> v4(v3); //(4)拷贝构造
}
带有空间配置器的构造函数,我们用它的缺省值。
value_type就是模板的第一个参数T,即容器中存放数据的类型。
通过调试,我们可以看到各个容器中的内容:
2、析构函数

析构函数就不用多说了,我们创建容器添加数据,要在堆上开辟动态空间,析构函数就是要来对这些开辟的空间进行释放的,从而销毁容器对象。编译器会自动调用析构函数,我们可以不用单独处理。
我们可以通过调试简单演示一下:
程序结束前:

程序结束后:

程序结束自动调用析构,销毁容器对象。
3、赋值重载

它的作用就是将 x 中的所有元素复制到容器中。
我们用代码来理解一下:
void test_vector2()
{vector<int> v1(2,6);vector<int> v2(3,1);v2 = v1;
}
调试结果:
赋值前:

赋值后:

从这两张图可以看出,当v2的size大小取决于v1,如果v2在赋值前容量比v1大,则赋值后保持不变,否则会扩容,保证能存放完v1的数据。
4、重载[]
因为vector的底层是动态数组,所以它也支持用[]来访问指定下标的元素。
void test_vector3()
{vector<int> v(6, 6);cout << v[0] << endl;cout << v[2] << endl;
}
在主函数中调用test_vector3()结果如下:

如果越界访问就会报错。
这里也有3种遍历容器的方法,和string差不多一样:
void test_vector4()
{vector<int> v1;vector<int> v2(10, 1);vector<int> v3(++v2.begin(), --v2.end());//1、重载[]for (size_t i = 0; i < v3.size(); i++){cout << v3[i] << " ";}cout << endl;//2、迭代器vector<int>::iterator it = v3.begin();while (it != v3.end()){cout << *it << " ";++it;}cout << endl;//3、范围forfor (auto e : v3){cout << e << " ";}cout << endl;
}
在主函数中调用test_vector4()结果如下:
这3种迭代方法,我们在string篇幅都已详细讲解了,大家如果不懂,可以看一下那篇文章。
5、扩容规律
我们可以看一下vector在添加元素时,自动扩容的规律:
void TestVectorExpand()
{size_t sz;vector<int> v;sz = v.capacity();cout << "capacity changed: " << sz << '\n';cout << "making v grow:\n";for (int i = 0; i < 100; ++i){v.push_back(i); //尾插if (sz != v.capacity()){sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}
在主函数中调用TestVectorExpand()结果如下:

不难发现,它是从0开始扩的,这与string是不同的,它是严格的1.5倍扩容。
6、成员函数
成员函数中大多和string用法和功能一样,这里只说一些特殊的。
(1)reserve()
它的功能是也是预留容量的,也就是改变capacity的大小,它可以避免频繁扩容。

size_type是一个无符号整形,它和string中的reserve()成员函数相似,但有一点不同,我们先往下看,假设参数是n(就是改变后的容量大小),分3种情况:
1、n < size
明确不会缩容。(这是和string不同的)
也不会改变size的大小,就是不会破坏原有内容。
2、size < n < capacity
明确不会缩容。(这是和string不同的)
3、n > capacity
会扩容,至少扩到n,也可能更多,这是不确定的。
我们写一段代码验证一下:
void test_vector5()
{vector<int> v(10, 1);cout << v.size() << endl;cout << v.capacity() << endl;//1、 n > capacityv.reserve(20); cout << v.size() << endl;cout << v.capacity() << endl;//2、size < n < capacityv.reserve(15);cout << v.size() << endl;cout << v.capacity() << endl;//3、n < sizev.reserve(5);cout << v.size() << endl;cout << v.capacity() << endl;
}
在主函数中调用test_vector5()结果如下:

根据结果显示,当n < capacity时,它是不会缩容的,这是明确的。
(2)resize()

它是将size设置为n,也分3种情况:
1、n < size
size的大小会变为n,其余的size - n个元素被删除(摧毁),但capacity通常不变。
2、size < n < capacity
size的大小会变为n,插入n - capacity个数据,如果不给第二个参数,那就用给的缺省值来初始化这n - capacity个数据,如果value_type是自定义类型,就调用它的默认构造,如果想自己初始化这n - capacity个数据,那么就手动给第二个参数赋值。
3、n > capacity
会扩容,至少扩到n,也可能更多,这是不确定的。在vs下通常会扩的更多一些。
对于前两点,缩不缩容不一定,这个需要看平台的处理。
我们写一段代码验证一下:
void test_vector6()
{vector<int> v(3, 1);v.reserve(8); //提前预留8字节空间cout << v.size() << endl;cout << v.capacity() << endl;//1、n < sizev.resize(1);cout << v.size() << endl;cout << v.capacity() << endl;//2、size < n < capacityv.resize(5, 3); //多余的n - size个数的数据初始化为3cout << v.size() << endl;cout << v.capacity() << endl;//3、size > capacityv.resize(10,100);//多余的n - size个数的数据初始化为100cout << v.size() << endl;cout << v.capacity() << endl;
}
在主函数中调用test_vector6()结果如下:

大家对比上面的3点进行理解。
(3)insert()
这里的insert比string当中的insert简洁了许多。

它在这不支持下标了,只支持迭代器。
void test_vector7()
{ vector<int> v2(2, 0);vector<int> v1(5, 1);for (auto e : v1)cout << e << " ";cout << endl;v1.insert(v1.begin(), 0); //(1)在v1头部位置插入0for (auto e : v1)cout << e << " ";cout << endl;v1.insert(v1.begin() + 3, 3, 100); //(2)在v1下标为3的位置上插入3个100for (auto e : v1)cout << e << " ";cout << endl;v1.insert(v1.end(), v2.begin(), v2.end());//(3)在v1的末尾,插入一段迭代区间for (auto e : v1)cout << e << " ";cout << endl;
}
在主函数中调用test_vector7()结果如下:

它不直接支持下标,但间接却是支持的,因为用迭代器就可以实现下标的问题,假设你要在下标为3的位置插入数据,那迭代器 v.begin() + 3就可以实现。这里没有用下标更多的原因是和后面的容器进行兼容,像list,它的底层不是动态数组,用下标访问就是不合适的。所以我们在容器这一部分,统一都用迭代器。
(4)erase()

同时,它也是只支持用迭代器来进行相应位置数据删除。
7、其他
vector不支持流插入和流提取,因为它的打印形式是多样的,不像string那样是固定的,遇到'\0'就终止打印,vector不支持流插入和流提取方便了我们对打印形式的控制,更自由和灵活。
vector底层是动态数组,string底层也是动态数组,那vector<char> 可以等同于string吗?
答案是不能。
首先,string定义的对象后面默认有'\0',vector<char>没有,其次,string定义的对象可以用字符串进行初始化,vector<char>不能,接着,string有很多针对字符串具有特定功能的接口,vector却没有,最后,string可以进行一些接口的传参,如果换用vector<char>则会麻烦许多。
所以vector<char> 是不可以取代string的。
三、结语
以上就是本篇的全部内容了,主要讲了vector的基本使用,希望大家有所收获,祝大家天天开心!
相关文章:
【C++】vector容器的基本使用
一、vector是什么 vector是STL第一个正式的容器,它的底层其实就是动态数组,插入数据时当容量满了会自动扩容,它和string差不多,不同的之处之一在于vector本身是一个模板,它这个容器中可以存放各种各样的类型的数据&am…...
【强化学习系列】Gym库使用——创建自己的强化学习环境2:拆解官方标准模型源码/规范自定义类+打包自定义环境
目录 一、 官方标准环境的获取与理解 二、根据官方环境源码修改自定义 1.初始化__init__() 2.重置环境 reset() 三、打包环境 1.注册与创建自定义环境 2.环境规范化 在本文的早些时候,曾尝试按照自己的想法搭建自定义的基于gym强化学习环境。 【强化学习系列】Gy…...
PyQt5实现按钮选择文件夹及文件夹
目录 1、选择文件夹并显示 2、选择文件 3、选择多个文件 4、设置保存文件路径 1、选择文件夹并显示 from PyQt5 import QtWidgetsdirectory QtWidgets.QFileDialog.getExistingDirectory(None, "选取文件夹", "./") # 起始路径 print(directory) 2…...
Gin渲染
HTML渲染 【示例1】 首先定义一个存放模板文件的 templates文件夹,然后在其内部按照业务分别定义一个 posts 文件夹和一个 users 文件夹。 posts/index.tmpl {{define "posts/index.tmpl"}} <!DOCTYPE html> <html lang"en">&…...
前端——JS基础
定义变量:let / var 字符串 字符串拼接: 字符串和数字拼:您.... 25 ; 这个25会转成字符串再拼接 字符串和数组拼:10以内的质数有: [2,3,5,7] > 10以内的质数有:2,3,5,7 字符串长度:leng…...
MATLAB入门教程
MATLAB安装教程可参考链接:matlab怎么安装 matlab安装教程-电脑软件-PHP中文网 1.MATLAB的工作环境 (1)命令窗(command window) 是对MATLAB进行操作的主要载体。默认情况下,启动MATLAB时就打开命令窗。MATLAB的所有所数…...
muduo - 概要简述
作者:陈硕 编程语言:C 架构模式:Reactor 代码链接:GitHub - chenshuo/muduo: Event-driven network library for multi-threaded Linux server in C11 设计自述:https://www.cnblogs.com/Solstice/archive/2010/08…...
Selenium点击元素的方法
前言 点击方法在web自动化测试中经常用到,下面就来介绍一下selenium常用和不常用的点击方法; 1、常用方法 1.1、使用 click() 方法: 这是最简单和最常用的方法。通过选中要点击的元素,然后使用 click() 方法来触发点击事件。 示例代码: element = self.driver.find_e…...
kali里面搭建docker容器
注意事项:kali版本,镜像源 (1)权限为管理员: sudo su (2) 更新软件包列表并升级已安装的软件包 apt-get update apt-get upgrade 出错了,应该是更新源出问题了。 (3)更换镜像源&am…...
WebGL系列教程八(GLSL着色器基础语法)
目录 1 前言2 基本原则3 基本数据类型4 顶点着色器和片元着色器4.1 声明4.2 初始化项目4.3 赋值 5 结构体5.1 声明5.2 赋值 6 函数6.1 基本结构6.2 自定义函数6.3 常用内置函数 7 精度8 其他9 总结 1 前言 通过前七讲,我们已经见过了WebGL中的部分基础语法ÿ…...
go多线程
1、简单使用(这个执行完成,如果进程执行比较久,这里不会等待它们结束) package mainimport "time"func main() {go func() {println("Hello, World!")}()time.Sleep(1 * time.Second) }2、wg.Add(数量)使用&…...
【话题】如何看待IBM中国研发部裁员?
(一)背景 在全球化的大趋势下,跨国公司的业务布局一直处于动态调整之中。IBM 作为全球知名的 IT 企业,在中国市场已经运营多年,其在中国的研发中心曾经为公司的全球业务发展做出了重要贡献。近年来,全球经…...
【C/C++】涉及string类的经典OJ编程题
【C/C】涉及string类的经典OJ编程题 一. 把字符串转化成整数(atoi)解法一:(不用long)完整代码:解法二:(用long) 二.字符串相加代码实现(含注释)&a…...
淘系等电商平台API接口系列:商品详情数据解析,json数据返回参考
——在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦! 在淘系(如淘宝、天猫)等电商平台中,商品详情数据…...
vue组件之间的数据共享
一、组件之间的关系 1.父子关系 2.兄弟关系 3.后代关系 二、父子组件之间的数据共享 1.父-->子共享数据 父组件通过v-bind属性绑定向子组件共享数据,子组件需要使用props接受数据。 <template><p>父组件</p><Son :msg"msg"…...
LangChain:构建强大的LLM应用的全方位框架
LangChain:构建强大的LLM应用的全方位框架 引言 在人工智能和大语言模型(LLMs)快速发展的今天,开发者们迫切需要一个强大而灵活的框架来简化LLM应用的开发过程。LangChain应运而生,它不仅提供了丰富的工具和组件&…...
自有平台自有品牌如何利用电商API接口做定价参考(多平台商品详情数据接口)
如今,多数自有商城自有品牌在为产品做定价时都会参考淘宝|天猫|京东等主流电商平台的商品价格以做参考,这一行为的好处主要有以下几点: 通过参考主流平台价格,用户更能了解目标市场中消费者对产品的接受度,从而制定出符…...
三万字长文Java面试题——基础篇(注:该篇博客将会一直维护 最新维护时间:2024年9月18日)
🧸本篇博客重在讲解Java基础的面试题,将会实时更新,欢迎大家添加作者文末联系方式交流 📜JAVA面试题专栏:JAVA崭新面试题——2024版_dream_ready的博客-CSDN博客 📜作者首页: dream_ready-CSDN博…...
数学建模——熵权+TOPSIS+肘部法则+系统聚类
文章目录 一、起因二、代码展示 一、起因 我本科的数学建模队长找上我,让我帮她写下matlab代码,当然用的模型还是曾经打比赛的模型,所以虽然代码量多,但是写的很快,也是正逢中秋,有点时间。 当然我也没想到…...
Java | Leetcode Java题解之第403题青蛙过河
题目: 题解: class Solution {public boolean canCross(int[] stones) {int n stones.length;boolean[][] dp new boolean[n][n];dp[0][0] true;for (int i 1; i < n; i) {if (stones[i] - stones[i - 1] > i) {return false;}}for (int i 1…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
