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

C++ vector的使用

目录

一、vector简介

二、vector的使用

三、vector的空间增长问题

reserve和resize

四、vector的迭代器使用

begin和end

rbegin和rend

五、vector的增删查改

push_back和pop_back

insert和erase

find函数

六、元素访问

七、vector迭代器失效问题

迭代器失效解决方法


一、vector简介

STL 中的 vector是 C++ 标准库中最核心的动态数组容器,用于替代原始数组,提供自动内存管理和丰富功能。

核心接口速查

// 构造
vector<int> vec;                // 空vector
vector<int> vec(100);           // 100个0
vector<int> vec(100, 5);        // 100个5// 元素访问
vec[0] = 10;                    // 无边界检查
vec.at(0) = 10;                 // 带边界检查(越界抛异常)
int* p = vec.data();            // 获取底层数组指针// 容量操作
vec.reserve(1000);              // 预分配内存(不初始化)
vec.resize(50);                 // 改变元素数量
vec.shrink_to_fit();            // 释放多余内存// 增删元素
vec.push_back(10);               // 尾部插入
vec.pop_back();                 // 尾部删除
vec.insert(vec.begin()+2, 20);  // 指定位置插入
vec.erase(vec.begin()+1);        // 删除指定位置// 工具函数
vec.empty();                     // 是否为空
vec.size();                      // 实际元素数量
vec.capacity();                  // 当前内存容量

vector是 STL 中综合性能最优的通用容器,适用于 >90% 需动态数组的场景。其核心优势在于随机访问性能 + 缓存局部性 + 自动内存管理,是现代 C++ 高性能编程的基础设施。

二、vector的使用

构造

1: 构造一个某类型的空容器。

vector<int> vec;                // 空vector

2: 构造一个含有n个val的某类型容器。

vector<int> vec(100, 5);        // 100个5

3:拷贝构造

vector<int> v3(v2); //拷贝构造int类型的v2容器的复制品

4:使用迭代器拷贝构造某一段内容

vector<int> v4(v2.begin(), v2.end()); //使用迭代器拷贝构造v2容器的某一段内容

vector存储的类型很多也可以是自定义类型

int main()
{vector<string> vstr;  //数组里存放的是string类string s1 = "张三";   vstr.push_back(s1);vstr.push_back("李四"); //隐式类型转换return 0;
}

三、vector的空间增长问题

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
reserve(重点)改变vector的capacity
resize(重点)改变vector的size

size和capacity

#include <iostream>
#include <vector>
using namespace std;int main()
{vector<int> vec(100, 5);cout << vec.size() << endl; //获取当前容器中的有效元素个数cout << vec.capacity() << endl; //获取当前容器的最大容量return 0;
}
reserve和resize

通过reserse函数改变容器的最大容量,resize函数改变容器中的有效元素个数。

reserve规则:
 1、当所给值大于容器当前的capacity时,将capacity扩大到该值。
 2、当所给值小于容器当前的capacity时,什么也不做。

resize规则:
 1、当所给值大于容器当前的size时,将size扩大到该值,扩大的元素为第二个所给值,若未给出,则默认为0。
 2、当所给值小于容器当前的size时,将size缩小到该值。

#include<iostream>
#include<vector>
using namespace std;int main()
{vector<int> v(5, 2);cout << v.size() << endl; //5cout << v.capacity() << endl; //5v.reserve(10); //改变容器的capacity为10,size不变cout << v.size() << endl; //5cout << v.capacity() << endl; //10v.resize(8); //改变容器的size为8cout << v.size() << endl; //8cout << v.capacity() << endl; //10return 0;
}

empty

通过empty函数判断当前容器(size)是否为空。

int main()
{vector<int> vec(10, 2);cout << vec.empty() << endl;//0 非空vector<int> v;cout << v.empty() << endl;//1 空return 0;
}

四、vector的迭代器使用

vector iterator 的使用

iterator的使用接口说明
begin()获取第一个数据位置的iterator/const_iterator
end()获取最后一个数据的下 一个位置的iterator/const_iterator
rbegin获取最后一个数据位置的reverse_iterator
rend()获取第一个数据前一个位置的reverse_iterator

begin和end

通过begin函数可以得到容器中第一个元素的正向迭代器,通过end函数可以得到容器中最后一个元素的后一个位置的正向迭代器

int main()
{vector<int> v(10, 2);//正向迭代器遍历容器vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";it++;}cout << endl;//2 2 2 2 2 2 2 2 2 2return 0;
}

rbegin和rend

通过rbegin函数可以得到容器中最后一个元素的反向迭代器,通过rend函数可以得到容器中第一个元素的前一个位置的反向迭代器。

 

int main()
{vector<int> v{0,1,2,3,4,5,6,7,8,9};for (int i = 0; i < 10; i++){v.push_back(i);}//反向迭代器遍历容器vector<int>::reverse_iterator rit = v.rbegin();while (rit != v.rend()){cout << *rit << " ";//9 8 7 6 5 4 3 2 1 0rit++;}cout << endl;return 0;
}

五、vector的增删查改

push_back和pop_back

通过push_back函数对容器进行尾插,pop_back函数对容器进行尾删。

int mian()
{vector<int> v{ 0,1,2,3,4};for (int i = 0; i < 10; i++){v.push_back(i);}v.pop_back();v.pop_back();//v 0 1 2return 0;
}

insert和erase

insert函数通过在指定位置的元素之前插入新元素来扩展向量,从而有效地将容器大小增加插入的元素数量。

通过erase函数可以删除所给迭代器位置的元素,或删除所给迭代器区间内的所有元素。

int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);//insert (iterator position, const value_type& val);v.insert(v.end(), 0); //在容器尾插入0//insert(iterator position, size_type n, const value_type & val);v.insert(v.begin(), 5, -1); //在容器开头插入5个-1//erase (iterator position);v.erase(v.begin()); //删除容器中的第一个元素//erase (iterator first, iterator last);v.erase(v.begin(), v.begin() + 5); //删除在该迭代器区间内的元素(左闭右开)return 0;
}

find函数

template <class InputIterator, class T>InputIterator find (InputIterator first, InputIterator last, const T& val);

find函数共三个参数,前两个参数确定一个迭代器区间(左闭右开),第三个参数确定所要寻找的值。
find函数在所给迭代器区间寻找第一个匹配的元素,并返回它的迭代器,若未找到,则返回所给的第二个参数。

int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector<int>::iterator pos = find(v.begin(), v.end(), 2); //获取值为2的元素的迭代器v.insert(pos, 10); //在2的位置插入10//1 10 2 3 4pos = find(v.begin(), v.end(), 3); //获取值为3的元素的迭代器v.erase(pos); //删除3//1 2 10 4return 0;
}

六、元素访问

vector当中实现了 [ ] 操作符的重载,因此我们也可以通过“下标+[ ]”的方式对容器当中的元素进行访问。

int main()
{vector<int> v(10, 1);//使用“下标+[]”的方式遍历容器for (size_t i = 0; i < v.size(); i++){v[i] = i;cout << v[i] << " ";}cout << endl;return 0;
}

七、vector迭代器失效问题

迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对 指针进行了封装,比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器 底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即 如果继续使用已经失效的迭代器,程序可能会崩溃)。

1. 会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、 assign、push_back等。

#include <iostream>
using namespace std;
#include <vector>
int main()
{vector<int> v{ 1,2,3,4,5,6 };auto it = v.begin();// 将有效元素个数增加到100个,多出的位置使用8填充,操作期间底层会扩容// v.resize(100, 8);// reserve的作用就是改变扩容大小但不改变有效元素个数,操作期间可能会引起底层量改变// v.reserve(100);// 插入元素期间,可能会引起扩容,而导致原空间被释放// v.insert(v.begin(), 0);// v.push_back(8);// 给vector重新赋值,可能会引起底层容量改变v.assign(100, 8);/*出错原因:以上操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的空间,而引起代码运行时崩溃。解决方式:在以上操作完成之后,如果想要继续通过迭代器操作vector中的元素,只需给it重新赋值即可。*/while (it != v.end()){cout << *it << " ";++it;}cout << endl;return 0;
}

迭代器失效解决方法

使用迭代器时,永远记住一句话:每次使用前,对迭代器进行重新赋值。

int main()
{vector<int> v{ 1,2,3,4,5,6 };auto it = v.begin();v.assign(100, 8);//这里重新定位了it让其指向新空间的起始it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;return 0;
}

http://www.dtcms.com/a/335845.html

相关文章:

  • 自动驾驶中的传感器技术34——Lidar(9)
  • 前端项目练习-王者荣耀竞赛可视化大屏 -Vue纯前端静态页面项目
  • Springboot项目3种视图(JSP、Thymeleaf、Freemarker)演示
  • 图解直接插入排序C语言实现
  • 3.逻辑回归:从分类到正则化
  • pyecharts可视化图表组合组件_Grid:打造专业数据仪表盘
  • 矿物分类案列 (一)六种方法对数据的填充
  • C#WPF实战出真汁13--【营业查询】
  • 《设计模式》工厂方法模式
  • 数据结构与算法之 leetcode 98. 验证二叉搜索树 (前序,中序,后序遍历)
  • 影刀 RAP 迁移华为云备忘录数据到得到笔记
  • GitHub Copilot:AI编程助手的架构演进与真实世界影响
  • mac电脑开发嵌入式基于Clion(stm32CubeMX)
  • 深入了解linux系统—— 线程控制
  • IDE/去读懂STM32CubeMX 时钟配置图(有源/无源晶振、旁路/晶振模式、倍频/分频)
  • 三、k8s 1.29 之 安装2
  • 重温k8s基础概念知识系列三(工作负载)
  • 什么是GD库?PHP中7大类64个GD库函数用法详解
  • Kafka 面试题及详细答案100道(23-35)-- 核心机制2
  • 基础IO_系统文件IO | 重定向【Linux】
  • 《程序员修炼之道》第三四章读书笔记
  • 《算法导论》第 27 章 - 多线程算法
  • scikit-learn/sklearn学习|套索回归Lasso解读
  • Ansible 核心功能进阶:自动化任务的灵活控制与管理
  • 自由职业数据科学:从细分定位到规模化的实战路线
  • 记忆翻牌游戏 greenfoot 开发
  • 机器人经验学习1 杂记
  • 电子电气架构 --- 自动驾驶汽车的下一步发展是什么?
  • Python自学10-常用数据结构之字符串
  • 机器学习算法篇(十三)------词向量转化的算法思想详解与基于词向量转换的文本数据处理的好评差评分类实战(NPL基础实战)