【C++】— 掌握STL vector 类:“Vector简介:动态数组的高效应用”
文章目录
- 1.vector的介绍和使用
- 1.1vector的介绍
- 1.2 vector的特点
- 1.3vector的使用
- 1.3.1vector的定义
- 1.3.2vector iterator的使用
- 1.3.3vector 的空间增长问题
- 1.3.4 vector 的增删查改
- 1.3.5vector 迭代器失效问题

1.vector的介绍和使用
1.1vector的介绍
vector是一个顺序容器,可以看作是能够动态增长和缩小的数组。与普通的数组不同的是,vector在需要时可以自动调整其大小,以容纳新添加的元素。因此vector在使用上更加的灵活和方便,
1.2 vector的特点
1.动态性:vector能够根据需要动态的调整其空间的大小,这使得vector在处理不确定数量的数据时非常有用。
2.随机访问: 与数组类似,vector支持通过下标进行数据的快速访问,这意味着可以在常数时间内访问vector中的任何元素。
3.尾部操作高效: 在vector尾部添加或者删除数据时非常高效的,因为这些操作在常数时间内就能完成。
1.3vector的使用
1.3.1vector的定义
| 构造函数说明 | 接口说明 |
|---|---|
| vector() | 无参构造 |
| vector(size_type n,const value_type& val = value_type()) | 构造并初始化n个value |
| vector(const vector& x) | 拷贝构造 |
| ector(inputlterator first,inputlterator last) | 使用迭代器进行初始化构造 |
代码演示:
1.默认构造函数
std::vector<T> v;
• 创建一个空的 vector,其元素类型为T。
• 初始时,v的大小为0容量也是未定义的(通常为0,具体取决于实现)
2.指定大小的构造函数
std::vector<T> v(n);
• 创建一个大小为n的vector,其元素被默认构造(即调用T())。
• 如果T是一个类型,并没有默认构造函数,则会编译报错。
3.指定大小和初始值的构造函数
std::vector<T> v(n,val);
• 创建一个大小为n的vector,并使用val初始化每个元素。
• 这对需要初始化所有元素为相同值的场景非常有用。
4.范围构造函数
std::vector<T> v(first,last);
• 创建一个vector,并使用迭代器范围[first,last)内的元素来初始化它。
• first和last是输入迭代器,它们指向某种容器(数组、另一个vector等)中的元素。
• 注意: first和last是左闭右开的,即包含first指向的元素,但不包括last指向的元素。
5.拷贝构造函数
std::vector<T> v2(v1);
• 创建一个新的vector,它是现有vector v1的一个副本。
• 新vector 将包含与v1 相同数量和顺序的元素。
6.移动构造函数(C++11 及以后)
std::vector<T> v2(std::move(v1));
• 创建一个新的vector,并通过移动v1 的内容来初始化它。
• 这通常比拷贝构造函数更加高效,因为它可以避免不必要的复制操作。
• 然而,v1在移动后将处于未定义状态,通常不再包含有效的数据。
7.初始化列表构造函数(C++11 及以后)
std::vector<T> v1 = {val1,val2,val3,...};
或者
std::vector<T> v1{val1,val2,val3,...};
• 使用初始化列表来创建并初始化一个vector.
• 这就允许你直接在构造函数中指定要包含在vector中的元素。
1.3.2vector iterator的使用
| iterator的使用 | 接口说明 |
|---|---|
| begin + end | 获取第一个数据位置的 iterator / const_iterator;获取最后一个数据下一个位置的 iterator / const_iterator |
| rbegin + rend | 获取最后一个数据的位置的 reverse_iterator;获取第一个为数据前一个位置的 revesr_iterator |


1.3.3vector 的空间增长问题
| 接口名称 | 接口说明 |
|---|---|
| size | 获取数据的个数 |
| capacity | 获取容量大小 |
| empty | 判断是否为空 |
| resize | 改变vector的size |
| reserve | 改变vector的capacity |
1.3.4 vector 的增删查改
| vector增删查改 | 接口说明 |
|---|---|
| push_back | 尾插 |
| popop_back | 尾删 |
| find | 查找(这个是算法模块实现,不是vector的接口) |
| insert | 在pos之前插入数据val |
| erase | 删除pos位置的数据 |
| swap | 交换两个vector的数据空间 |
| operator[] | 像数组一样访问 |
代码演示:
#include<iostream>
#include<vector>
using namespace std;int main()
{//创建一个空的vectorvector<int> v;//增加元素v.push_back(10);v.push_back(20);v.insert(v.begin() + 1,15); //在第二个位置插入15// 打印 vector 中的元素cout << "Vector after insertions: ";for (int i = 0; i < v.size(); ++i) {std::cout << v[i] << " ";}cout << endl;// 查找元素auto it = find(v.begin(), v.end(), 20);if (it != v.end()) {cout << "Found 20 at position: " << distance(v.begin(), it) << endl;}else {cout << "20 not found in the vector." << endl;}// 修改元素v[1] = 18; // 将第二个元素修改为 18// 打印修改后的 vector 中的元素cout << "Vector after modification: ";for (int i = 0; i < v.size(); ++i) {cout << v[i] << " ";}cout << endl;// 删除元素(删)v.erase(find(v.begin(), v.end(), 10)); // 删除第一个值为 10 的元素v.pop_back(); // 删除末尾的元素// 打印删除后的 vector 中的元素cout << "Vector after deletions: ";for (int i = 0; i < v.size(); ++i) {cout << v[i] << " ";}cout << endl;return 0;
}
运行这段代码将输出:

1.3.5vector 迭代器失效问题
迭代器的主要作用就是让算法能够不用关系底层数据结构,其底层实际就是一个类似于指针的东西,或者对指针进行了封装。比如:vector的迭代器就是原生态指针 T*。因此迭代器失效,实际就是迭代器底层对应指针指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。
对于vector可能导致其迭代器失效的操作有:
1.插入操作导致内存重新分配:
•当向vector中添加元素,且当前容量不足以容纳新的元素时,vector可能会重新分配其内存空间(即分配更大的内存块,并将现有元素复制到新的位置)。这种情况下,所有指向原vector元素的迭代器、指针和引用都会失效。
•插入操作包括push_back、emplace_back、insert等。
2.删除操作:
•删除元素(使用erase方法)会使指向被删除元素及其之后的元素的迭代器失效。这是因为删除操作会移动后续元素来填补被删除元素的位置。
3.改变vector的大小:
•使用resize方法改变vector的大小,如果新大小大于当前大小,并导致内存重新分配,那么所有迭代器都会失效。
4.清空vector:
• 使用clear方法清空vector会使所有的迭代器失效,因为所有元素都被移除了。
如何避免迭代器失效
• 预留空间: 如果知道将要插入的元素的数量,可以使用reserve方法预先分配足够的空间。这可以减少内存重新分配的可能性,从而避免迭代器失效。
• 使用返回值: 一些vector成员函数(如insert和erase)会返回指向新元素位置或者下一个有效元素的迭代器。使用这些返回值可以避免因操作导致的迭代器失效问题。
• 重新获取迭代器: 在可能导致迭代器失效的操作后,重新获取迭代器。
示例代码:
#include<iostream>
#include<vector>
using namespace std;int main()
{vector<int> v = {1,2,3,4,5};//获取初始迭代器auto it = v.begin();//插入元素,可能导致迭代器失效v.insert(v.begin(), 0);//使用重新获取的迭代器it = v.begin();//重新获取迭代器cout << "插入后的第一个元素:" << *it << endl;//删除元素,可能导致迭代器失效v.erase(it);//使用erase的返回值it = v.erase(v.begin()); //删除第一个元素,并获取新的迭代器cout << "删除后的第一个元素:" << *it << endl;return 0;
}
总之,使用 vector 时需要特别注意迭代器的有效性,尤其是在进行插入和删除操作时。通过预留空间、使用函数返回值和适时重新获取迭代器,可以有效地管理迭代器的生命周期,避免潜在的失效问题。
相关文章:
【C++】— 掌握STL vector 类:“Vector简介:动态数组的高效应用”
文章目录 1.vector的介绍和使用1.1vector的介绍1.2 vector的特点1.3vector的使用1.3.1vector的定义1.3.2vector iterator的使用1.3.3vector 的空间增长问题1.3.4 vector 的增删查改1.3.5vector 迭代器失效问题 1.vector的介绍和使用 1.1vector的介绍 vector是一个顺序容器&am…...
Docker__持续更新......
Docker 1. 基本知识1.1 为什么有Docker?1.2 Docker架构与容器化 画图解释 画图解释2. 项目实战 1. 基本知识 1.1 为什么有Docker? 用一行命令跨平台安装项目,在不同平台上运行项目。把项目打包分享运行应用。 1.2 Docker架构与容器化 准备机器,在机…...
【R语言】主成分分析与因子分析
一、主成分分析 主成分分析(Principal Component Analysis, PCA)是一种常用的无监督数据降维技术,广泛应用于统计学、数据科学和机器学习等领域。它通过正交化线性变换将(高维)原始数据投影到一个新的坐标系ÿ…...
ROS-相机话题-获取图像-颜色目标识别与定位-目标跟随-人脸检测
文章目录 相机话题获取图像颜色目标识别与定位目标跟随人脸检测 相机话题 启动仿真 roslaunch wpr_simulation wpb_stage_robocup.launch rostopic hz /kinect2/qhd/image_color_rect/camera/image_raw:原始的、未经处理的图像数据。 /camera/image_rectÿ…...
STM32 如何使用DMA和获取ADC
目录 背景 摇杆的原理 程序 端口配置 ADC 配置 DMA配置 背景 DMA是一种计算机技术,允许某些硬件子系统直接访问系统内存,而不需要中央处理器(CPU)的介入,从而减轻CPU的负担。我们可以通过DMA来从外设…...
【JAVA实战】JAVA实现Excel模板下载并填充模板下拉选项数据
背景 有这样一个场景:前端下载Excel模板,进行数据导入,这个下载模板过程需要经过后端接口去数据库查询数据进行某些列的下拉数据填充,下拉填充的数据过程中会出现错误String literals in formulas can’t be bigger than 255 cha…...
java面试笔记(一)
1. 一万个string类型的数据,设计一个算法如何按照String长度来排序 以使用 Arrays.sort() 方法,并结合一个自定义的比较器。以下是实现的示例代码: public class StringLengthSort {public static void main(String[] args) {// 定义一万个字符串的示例…...
【C++】36.C++IO流
文章目录 1. C语言的输入与输出2. 流是什么3. CIO流3.1 C标准IO流3.2 C文件IO流 4. stringstream的简单介绍 1. C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 scanf(): 从标准输入设备(键盘)读取数据,并将值存放在变量中。pri…...
Qt5开发入门指南:从零开始掌握跨平台开发
目录 Qt框架概述 开发环境搭建 基础语法与核心机制 第一个Qt窗口程序 常见问题解答 一、Qt框架概述 1.1 什么是Qt? Qt是一个1995年由挪威Trolltech公司开发的跨平台C图形用户界面应用程序框架。最新Qt5版本主要包含: GUI模块:支持Wind…...
Rook-ceph(1.92最新版)
安装前准备 #确认安装lvm2 yum install lvm2 -y #启用rbd模块 modprobe rbd cat > /etc/rc.sysinit << EOF #!/bin/bash for file in /etc/sysconfig/modules/*.modules do[ -x \$file ] && \$file done EOF cat > /etc/sysconfig/modules/rbd.modules &l…...
深度学习在蛋白质-蛋白质相互作用(PPI)领域的研究进展(2022-2025)
一、蛋白质-蛋白质相互作用(PPI)的定义与生物学意义 蛋白质-蛋白质相互作用(Protein-Protein Interaction, PPI)是指两个或多个蛋白质通过物理结合形成复合物,进而调控细胞信号传导、代谢、免疫应答等生命活动的过程。PPI是生物体内复杂功能网络的核心,例如酶与底物的结…...
网络安全学习架构 网络安全架构内容
网上买的《信息安全原理及应用》的书还没到,就找了一本《密码编码学与网络安全》的电子书,写的也不错,计划今天和明天把第一章绪论和第二章的数论给看完 1. 计算机网络安全概念 计算机安全的三个核心是:完整性(只要特…...
硕成C语言24
不管风吹浪打,胜似闲庭信步! 1.选择排序: 不管风吹浪打,胜似闲庭信步!1.选择排序: // 这个宏定义用于忽略 Visual Studio 中一些安全相关的警告,使得可以使用像 scanf 这样的函数而不产生警告…...
《Stable Diffusion绘画完全指南:从入门到精通的Prompt设计艺术》-配套代码示例
第一章:模型加载与基础生成 1.1 基础模型加载 from diffusers import StableDiffusionPipeline import torch# 加载SD 1.5基础模型(FP32精度) pipe StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5",…...
Linux下为Intel核显安装OpenCL
实验环境 CPU:N5105运行内存:32G系统:almalinux 8 (类似CentOS系统) 安装过程 检查i915驱动 输入命令dmesg | grep i915查看驱动的加载信息。 我这里没接显示器,输出正确的驱动加载信息如下图所示&…...
用deepseek学大模型04-机器学习建模过程
https://metaso.cn/s/7tEmBHr 目前已经学完深度学习的数学基础,给出机器学习建模的基本过程 好的,我现在需要回答用户的问题:已经学完深度学习的数学基础,现在要给出机器学习建模的基本过程。我需要结合我搜索到的资料来构建一个详…...
【ClickHouse】Ubuntu下离线安装ClickHouse数据库并使用DBeaver连接
目录 0. 安装前准备1 安装ClickHouse1.1 下载安装包1.2 离线安装1.3 配置密码1.4 启动ClickHouse服务 2 DBeaver连接配置2.1 下载ClickHouse驱动2.2 DBeaver配置2.2.1 配置主要参数2.2.2 配置驱动 2.3 常见问题处理2.3.1 修改远程登录配置2.3.2 更新驱动配置 0. 安装前准备 有…...
Unity3D实现接入DeepSeek对话
系列文章目录 unity知识点 文章目录 系列文章目录👉前言👉一、使用第一步👉1-1、登录注册DeepSeek👉1-2、创建API-key👉二、使用第二步👉三、使用第三步👉壁纸分享👉总结👉前言 随着人工智能和机器学习技术的不断进步,DeepSeek的未来发展趋势充满了无限可能…...
【ISO 14229-1:2023 UDS诊断(会话控制0x10服务)测试用例CAPL代码全解析②】
ISO 14229-1:2023 UDS诊断【会话控制0x10服务】_TestCase02 作者:车端域控测试工程师 更新日期:2025年02月15日 关键词:UDS诊断、0x10服务、诊断会话控制、ECU测试、ISO 14229-1:2023 TC10-002测试用例 用例ID测试场景验证要点参考条款预期…...
前端新手必看:10 大 UI 组件库全面解析,快速搭建高质量 Web 应用」 「从零开始:Vue 和 React 最受欢迎的 UI 组件库入门指南」 「超实用!PC 端和移动端 UI 组件库推荐与实战
前端新手必看:10 大 UI 组件库全面解析,快速搭建高质量 Web 应用 目录 什么是 UI 组件库?为什么需要 UI 组件库?PC 端 UI 组件库推荐 Ant DesignElement UIVuetifyBootstrapVueiView (View UI)Quasar FrameworkMaterial-UI (MUI…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
