当前位置: 首页 > news >正文

C++----STL(vector)

vector的介绍

vector的文档介绍:cplusplus.com/reference/vector/vector/

1.基本概念

  • 简单来说,vector是表示可以改变大小的数组的顺序容器。
  • 使用连续的存储位置来存储元素,因此可以通过常规指针的偏移量来高效访问。

2.内部机制

  • vector内部使用动态分配的数组来存储元素。
  • 插入新元素时,数组可能需要重新分配以增大尺寸,这是一项相对昂贵的任务。为避免频繁重新分配,vector可能会分配一些额外的存储空间以适应可能的增长。
  • vector的实际容量可能大于存储元素所需的空间(即大小)。

3.内存管理

  • 库采用不同的增长策略来平衡内存使用和重新分配。
  • 重新分配通常只在大小以对数增长间隔发生时进行,以提供摊还常数时间复杂度的插入操作(如push_back)。
  • 与数组相比,向量消耗更多内存,但具备管理和动态增长存储的能力。

4.vector的原型

vector的使用

vector 学习时一定要学会查看文档 vector 在实际中非常的重要,在实际中我们熟悉常见的接口就可以,下面列出了哪些接口是要重点掌握的。(vector与string都基于顺序表实现,因此接口相似。如果已经掌握string用法的,理解vector会更容易。后续讲解将简要提及相似之处,重点介绍vector的特有特性和用法。)

迭代器

begin()

  • 功能说明:返回一个指向vector第一个元素的迭代器。
  • 注意:有可读可写和只读两种迭代器。

rbegin()

  • 功能说明:返回一个指向vector最后一个元素的迭代器。
  • 同样有可读可写和只读两种。(下面讲解的迭代器都如此)

end()

  • 功能说明:返回一个指向vector最后一个元素之后位置的迭代器。

rend()

  • 功能说明:返回一个指向vector第一个元素之前位置的反向迭代器。

构造函数

1.使用填充构造

//原型:explicit vector (size_type n, const value_type& val = value_type(),const allocator_type& alloc = allocator_type());
vector<int> v1(10, 1);//创建一个包含10个整数的vector,每个整数初始化为1
vector<string> v2(10, "***");//创建一个包含10个字符串的vector,每个字符串初始化为"***"

2.使用迭代器范围构造

//原型:template <class InputIterator> vector (InputIterator first, InputIterator last,const allocator_type& alloc = allocator_type());
vector<int> v3(v1.begin(), v1.end());//使用v1的迭代器范围构造v3string str("hello world");
vector<char> v4(str.begin(), str.end());//使用字符串string的迭代器范围构造字符vector v4int a[] = {16, 2, 77, 29};
vector<int> v5(a, a + 4); // 使用数组a的迭代器范围构造v5

补充:配合sort函数的使用进行升序和降序排序

sort(v5.begin(), v5.end()); // 使用默认比较器(less<int>)对v5进行升序排序
sort(v5.begin(), v5.end(), greater<int>()); // 使用greater<int>比较器对v5进行降序排序
sort(v5.rbegin(),v5.rend()); // 使用反向迭代器对v5进行降序排序
sort(str.begin(), str.end()); // 对字符串str进行字典序排序
sort(a, a + 4); // 对数组a进行排序

容量相关的操作

size()

  • 功能说明:返回vector中当前元素的个数。

max_size()

  • 功能说明:返回vector中能容纳的最大元素个数。

capacity()

  • 功能说明:返回vector在当前情况下能容纳的元素个数。

reserve()

  • 功能说明:扩容。
  • 注意:reserve不改变vector的大小(即size()的值),也不初始化新分配的内存。
  • 易错展示:
    vector<int> v1;
    v1.reserve(10);
    for (size_t i = 0; i < 10; i++) {v1[i] = i; // 错误:v1.size()仍为0,访问v1[i]是未定义行为。
    }
  •  正确做法:
    vector<int> v1;
    v1.reserve(10);
    for (size_t i = 0; i < 10; i++) {v1.push_back(i); // 正确:使用push_back添加元素并初始化。
    }

resize()

  • 功能说明:扩容+初始化
    vector<int> v1;
    v1.resize(10); // 改变大小为10,新元素初始化为0(对于int类型)。
    for (size_t i = 0; i < 10; i++) {v1[i] = i; // 正确:v1的大小已经是10。
    }

empty()

  • 功能:检查vector是否为空。如果vector的大小为0,则返回true;否则返回false

shrink_to_fit()

  • 功能:请求移除vector中多余的容量。调用后,vector的容量将被调整为当前大小(即size()的值),前提是这不会增加内存分配的总大小。

元素访问

operator[]

  • 功能:通过索引访问vector中的元素。
  • 注意:不进行边界检查,如果索引超出范围,则行为未定义,可能导致程序崩溃或数据损坏)
    vector<int> v = {1, 2, 3};int first = v[0]; // 访问第一个元素,值为1。

at()

  • 功能:通过索引访问vector中的元素。
  • 与operator[]不同,at会进行边界检查。如果索引超出范围,则抛出std::out_of_range异常。
    vector<int> v = {1, 2, 3};int second = v.at(1); // 访问第二个元素,值为2。

data()

  • 功能说明:返回指向vector中第一个元素的指针(类型为T*,其中T是vector存储的元素类型)。如果vector为空,则返回空指针。
  • 类似于string中的c_str()方法,但data返回的是可修改的指针。
    vector<int> v = {1, 2, 3};int* ptr = v.data();cout << ptr[0] << " " << ptr[1] << " " << ptr[2] << endl; // 输出:1 2 3

修改操作

push_back()

  • 功能:在vector末尾添加一个元素。

pop_back()

  • 功能:移除vector末尾的元素.

insert()

  • 功能:在指定位置插入一个或多个元素。
    int a[] = { 16,2,77,29,3,33,43,3,2,3,3,2 };vector<int> v1(a, a + sizeof(a)/sizeof(int));// 头插 v1.insert(v1.begin(), 100);

erase()

  • 功能:移除指定位置的元素或一段元素。
    int a[] = { 16,2,77,29,3,33,43,3,2,3,3,2 };vector<int> v1(a, a + sizeof(a)/sizeof(int));// 头删v1.erase(v1.begin());// 删除第3个数据v1.erase(v1.begin() + 2);

注意:std::vector中使用eraseinsert后迭代器失效的情况

在C++的STL(标准模板库)中,vector是一个动态数组,其内存可以重新分配和移动。因此,当你对vector进行eraseinsert,可能会导致指向vector元素的迭代器失效。失效的迭代器不能再被用来访问vector中的元素,因为这样做会导致未定义行为。

下面的代码例子,展示了在std::vector中使用erase后迭代器失效的情况:

#include <iostream>
#include <vector>
using namespace std;int main() {vector<int> vec = { 1, 2, 3, 4, 5 };// 创建一个指向vector中第三个元素的迭代器auto it = vec.begin() + 2; // 指向3// 输出迭代器指向的值cout << "Before erase: " << *it << endl; // 输出: 3// 删除迭代器指向的元素vec.erase(it);// 此时it已经失效for (auto e : vec) {cout << e << " ";}cout << endl;// 下面的代码是未定义行为,因为it已经失效// cout << "After erase (undefined behavior): " << *it << endl; // 不要这样做return 0;
}

正确做法:

#define _CRT_SECURE_NO_EARNINGS 1
#include <iostream>
#include <vector>
using namespace std;int main() {vector<int> vec = { 1, 2, 3, 4, 5 };// 创建一个指向vector中第三个元素的迭代器auto it = vec.begin() + 2; // 指向3// 输出迭代器指向的值cout << "Before erase: " << *it << endl; // 输出: 3// 删除迭代器指向的元素it = vec.erase(it);// 我们可以获取删除元素后的下一个元素for (auto e : vec) {cout << e << " ";}cout << endl;cout << "After erase (undefined behavior): " << *it << endl; // 此时的it指向被删除的位置的下一个元素4return 0;
}

下面的代码例子,展示了在std::vector中使用insert后迭代器失效的情况:

#define _CRT_SECURE_NO_EARNINGS 1
#include <iostream>
#include <vector>
using namespace std;int main() {vector<int> vec = { 1, 2, 3, 4, 5 };vector<int>::iterator it = vec.begin() + 2;cout << "it: " << *it << endl;// 插入新元素vec.insert(vec.begin(), 10); // 在开头插入10for (auto e : vec) {cout << e << " ";}cout << endl;// 所有指向vec元素的迭代器(包括end()之前的迭代器)都可能失效// 下面的代码同样是未定义行为,因为之前的迭代器(即使它们没有直接指向被插入的位置)也可能不再有效// cout << "After insert (undefined behavior): " << *it << endl; // 这是错误的return 0;
}

正确做法:

#define _CRT_SECURE_NO_EARNINGS 1
#include <iostream>
#include <vector>
using namespace std;int main() {vector<int> vec = { 1, 2, 3, 4, 5 };vector<int>::iterator it = vec.begin() + 2;cout << "it: " << *it << endl;// 插入新元素vec.insert(vec.begin(), 10); // 在开头插入10for (auto e : vec) {cout << e << " ";}cout << endl;// 正确的做法是重新获取迭代器it = vec.begin() + 2;cout << "After insert (undefined behavior): " << *it << endl; return 0;
}

swap()

  • 功能:交换两个vector的内容。

clear()

  • 功能:移除vector中的所有元素,使其变为空容量。

assign()

  • 功能:清楚vector中的值,并用新值重新赋值。
    v1.assign(10, 1); // 将v1重新赋值为10个1

补充:find在 vector 中的应用

vector中的find:vector不像string在成员函数中直接提供了find(),而是通过<algorithm>头文件中的find函数,用于查找元素的位置。

#include<iostream>
#include<algorithm>
using namespace std;int main()
{int a[] = { 16,2,77,29,3,33,43,3 };vector<int> v1(a, a + sizeof(a)/sizeof(int));auto pos = find(v1.begin(), v1.end(), 3); // 在v1中查找元素3// 删除第3个数据v1.erase(v1.begin()+2);return 0;
}

迭代器失效问题

#include<iostream>
#include<algorithm>
using namespace std;int main()
{int a[] = { 16,2,77,29,3,33,43,3 };vector<int> v1(a, a + sizeof(a)/sizeof(int));auto pos = find(v1.begin(), v1.end(), 3); // 在v1中查找元素3// 删除所有的3 -- 涉及迭代器失效!后面解决while(pos != v1.end()){v1.erase(pos);pos = find(v1.begin(), v1.end(), 3); // 可能导致无限循环,因为pos可能已失效}return 0;
}

原因:vector在insert或erase操作后,可能会重新分配内存(尤其是当容量不足时),导致所有指向该vector的迭代器失效。

解决:

    while((pos = find(v1.begin(), v1.end(), 3)) != v1.end()){v1.erase(pos);}

相关文章:

C++----STL(vector)

vector的介绍 vector的文档介绍&#xff1a;cplusplus.com/reference/vector/vector/ 1.基本概念 简单来说&#xff0c;vector是表示可以改变大小的数组的顺序容器。使用连续的存储位置来存储元素&#xff0c;因此可以通过常规指针的偏移量来高效访问。 2.内部机制 vector…...

Ubuntu24.04初始化MySQL报错 error while loading shared libraries libaio.so.1

Ubuntu24.04初始化MySQL报错 error while loading shared libraries: libaio.so.1 问题一&#xff1a;libaio1不存在 # 提示libaio1不存在 [rootzabbix-mysql-master.example.com x86_64-linux-gnu]#apt install numactl libaio1 Reading package lists... Done Building depe…...

初探大数据流式处理

文章目录 初探大数据流式处理批式处理系统特点流式处理系统特点大批次计算微批次计算适用场景 流式计算的应用场景流式大数据的特征流式计算的关键技术流式处理框架的特征三大流式数据处理框架 初探大数据流式处理 大数据处理系统主要分为批式处理和流式处理两类。批式处理将大…...

【Linux】Linux入门(三)权限

目录 前提权限概念whoami指令 Linux权限管理文件访问者的分类&#xff08;人&#xff09;file指令权限信息权限的表示方法 chmod指令 更改权限chown指令 修改文件&#xff0c;文件夹所属用户和用户组 权限掩码umask&#xff08;权限掩码&#xff09; 粘滞位 前提 请先看下面这…...

html,css,js的粒子效果

这段代码实现了一个基于HTML5 Canvas的高级粒子效果&#xff0c;用户可以通过鼠标与粒子进行交互。下面是对代码的详细解析&#xff1a; HTML部分 使用<!DOCTYPE html>声明文档类型。<html>标签内包含了整个网页的内容。<head>部分定义了网页的标题&#x…...

Spring Boot + Netty + WebSocket 实现消息推送

1、关于Netty Netty 是一个利用 Java 的高级网络的能力&#xff0c;隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架。 2、Maven依赖 <dependencies><!-- https://mvnrepository.com/artifact/io.netty/netty-all --><dependency><gr…...

Python3 【字符串】:方法和函数使用示例手册

Python3 【字符串】&#xff1a;方法和函数使用示例手册 Python 提供了丰富的字符串处理方法和函数&#xff0c;以下是一些常用的方法和函数分类整理&#xff0c;并提供详细使用示例&#xff0c;简单易懂&#xff0c;值得收藏。 1. 字符串大小写转换 str.upper()&#xff1a;…...

数据结构与算法整理复习(一):数据结构概念与线性表

目录 第一章&#xff1a;绪论 1.1 数据结构的基本概念 1.2 算法与算法评价 第二章&#xff1a;线性表 2.1 线性表的定义和基本操作 2.2 线性表的顺序表示&#xff08;顺序表&#xff09; 应用题 2.3 线性表的链式表达&#xff08;链表&#xff09; 2.3.1 单链表 2.3.2…...

【Block总结】PConv风车卷积,更大的感受野,提高特征提取能力|即插即用

论文信息 论文标题&#xff1a;《Pinwheel-shaped Convolution and Scale-based Dynamic Loss for Infrared Small Target Detection》 论文链接&#xff1a;https://arxiv.org/pdf/2412.16986 GitHub链接&#xff1a;https://github.com/JN-Yang/PConv-SDloss-Data 创新点 …...

Python新春烟花

目录 系列文章 写在前面 技术需求 完整代码 下载代码 代码分析 1. 程序初始化与显示设置 2. 烟花类 (Firework) 3. 粒子类 (Particle) 4. 痕迹类 (Trail) 5. 烟花更新与显示 6. 主函数 (fire) 7. 游戏循环 8. 总结 注意事项 写在后面 系列文章 序号直达链接爱…...

VirtualBox can‘t enable the AMD-V extension

个人博客地址&#xff1a;VirtualBox cant enable the AMD-V extension | 一张假钞的真实世界 最近一次完成Deepin的系统更新后&#xff0c;进入VirtualBox创建的虚拟机&#xff08;Widows10&#xff09;时&#xff0c;出现以下错误&#xff1a; 根据网址“https://askubuntu.…...

掘金--创意标题匹配问题

问题描述 在广告平台中&#xff0c;为了给广告主一定的自由性和效率&#xff0c;允许广告主在创造标题的时候以通配符的方式进行创意提交。线上服务的时候&#xff0c;会根据用户的搜索词触发的 bidword 对创意中的通配符&#xff08;通配符是用成对 {} 括起来的字符串&#x…...

OBU和T-Box

OBU&#xff08;On-Board Unit&#xff0c;车载单元&#xff09;和T-Box&#xff08;Telematics Box&#xff0c;远程信息处理控制单元&#xff09;都是用于车联网和智能交通系统的车载设备&#xff0c;但它们的功能、应用场景和技术特点存在显著差异。以下是两者的详细对比&am…...

【PVE】Proxmox VE8.0+创建LXC容器安装docker

为了不影响PVE宿主机&#xff0c;通常使用套娃的形式安装Docker容器&#xff0c;再安装相关docker应用。首先在CT模板中创建 Linux 容器&#xff0c;推荐使用Debian。开启ssh登录&#xff0c;修改debian配置&#xff0c;安装docker 一、创建 LXC 容器 1、CT模板下载 点击“模…...

一文大白话讲清楚webpack基本使用——11——chunkIds和runtimeChunk

文章目录 一文大白话讲清楚webpack基本使用——11——chunkIds和runtimeChunk1. 建议按文章顺序从头看&#xff0c;一看到底&#xff0c;豁然开朗2. 啥是chunkIds3.怎么使用chunkIds4. 啥是runtimeChunk5. 怎么使用runtimeChunk 一文大白话讲清楚webpack基本使用——11——chun…...

Java 中的设计模式:经典与现代实践

Java 中的设计模式&#xff1a;经典与现代实践 1. 设计模式简介 设计模式是一种软件开发中的思想&#xff0c;它为我们提供了一些经过验证的、能够应对常见问题的解决方案。学习和掌握设计模式能够让开发者在面对复杂的需求时&#xff0c;能够设计出更加灵活、可维护的代码。…...

DRG_DIP 2.0时代医院程序结构转型与数据结构优化研究

一、引言 1.1 DRG_DIP 2.0 改革背景与意义 医保支付方式改革在医疗保障制度改革中占据着极为关键的地位&#xff0c;是推动医疗领域变革的核心力量。它犹如一把精准的手术刀&#xff0c;对医疗资源的合理分配、医疗服务质量的稳步提升以及医疗费用的有效控制起着决定性作用。…...

一部手机如何配置内网电脑同时访问内外网

做过运维的朋友都知道&#xff0c;最麻烦的是运维电脑不能远程&#xff0c;每次都得现场进行维护&#xff0c;明明客户那边有可以访问内网的电脑&#xff0c;怎么操作能将这台电脑能访问跟到外网呢&#xff0c;这样不就能通过远程软件远程了吗&#xff1f;嘿嘿。按以下步骤试试…...

国产低功耗带LCD驱动和触摸按键功能的MCU

以下是国产低功耗、集成LCD驱动和触摸按键功能的MCU精选型号及其核心特性&#xff0c;结合性能、功耗和适用场景进行综合推荐&#xff1a; 1.灵动微MM32L0130系列 257 核心特性&#xff1a;低功耗&#xff1a;待机模式功耗低至100nA&#xff0c;支持多种低功耗模式。 LCD驱动&a…...

XCP 协议基础

文章目录 一、XCP 简介二、XCP的主要功能三、什么是标定四、什么时候进行标定五、标定的意义六、标定的三层架构XCP协议 和 CCP协议的区别参考 一、XCP 简介 XCP 协议的全称为 eXtended Calibration Protocol&#xff0c;即扩展标定协议。 另有其他定义&#xff0c;XCP 协议全…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

Spring Boot + MyBatis 集成支付宝支付流程

Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例&#xff08;电脑网站支付&#xff09; 1. 添加依赖 <!…...

02.运算符

目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&&#xff1a;逻辑与 ||&#xff1a;逻辑或 &#xff01;&#xff1a;逻辑非 短路求值 位运算符 按位与&&#xff1a; 按位或 | 按位取反~ …...

MySQL体系架构解析(三):MySQL目录与启动配置全解析

MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录&#xff0c;这个目录下存放着许多可执行文件。与其他系统的可执行文件类似&#xff0c;这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中&#xff0c;用…...

【java面试】微服务篇

【java面试】微服务篇 一、总体框架二、Springcloud&#xff08;一&#xff09;Springcloud五大组件&#xff08;二&#xff09;服务注册和发现1、Eureka2、Nacos &#xff08;三&#xff09;负载均衡1、Ribbon负载均衡流程2、Ribbon负载均衡策略3、自定义负载均衡策略4、总结 …...

从零手写Java版本的LSM Tree (一):LSM Tree 概述

&#x1f525; 推荐一个高质量的Java LSM Tree开源项目&#xff01; https://github.com/brianxiadong/java-lsm-tree java-lsm-tree 是一个从零实现的Log-Structured Merge Tree&#xff0c;专为高并发写入场景设计。 核心亮点&#xff1a; ⚡ 极致性能&#xff1a;写入速度超…...

npm安装electron下载太慢,导致报错

npm安装electron下载太慢&#xff0c;导致报错 背景 想学习electron框架做个桌面应用&#xff0c;卡在了安装依赖&#xff08;无语了&#xff09;。。。一开始以为node版本或者npm版本太低问题&#xff0c;调整版本后还是报错。偶尔执行install命令后&#xff0c;可以开始下载…...

el-amap-bezier-curve运用及线弧度设置

文章目录 简介示例线弧度属性主要弧度相关属性其他相关样式属性完整示例链接简介 ‌el-amap-bezier-curve 是 Vue-Amap 组件库中的一个组件,用于在 高德地图 上绘制贝塞尔曲线。‌ 基本用法属性path定义曲线的路径,可以是多个弧线段的组合。stroke-weight线条的宽度。stroke…...

RKNN开发环境搭建2-RKNN Model Zoo 环境搭建

目录 1.简介2.环境搭建2.1 启动 docker 环境2.2 安装依赖工具2.3 下载 RKNN Model Zoo2.4 RKNN模型转化2.5编译C++1.简介 RKNN Model Zoo基于 RKNPU SDK 工具链开发, 提供了目前主流算法的部署例程. 例程包含导出RKNN模型, 使用 Python API, CAPI 推理 RKNN 模型的流程.   本…...