当前位置: 首页 > 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.xdnf.cn/news/1317223.html

相关文章:

  • 10 SQL进阶-SQL优化(8.15)
  • 说一下事件委托
  • Java 大视界 -- Java 大数据分布式计算在基因测序数据分析与精准医疗中的应用(400)
  • 【UEFI系列】ACPI
  • 跨越南北的养老对话:为培养“银发中国”人才注入新动能
  • JavaScript 性能优化实战:从评估到落地的全链路指南
  • Spark03-RDD02-常用的Action算子
  • 在鸿蒙中实现深色/浅色模式切换:从原理到可运行 Demo
  • E2B是一个开源基础设施,允许您在云中安全隔离的沙盒中运行AI生成的代码和e2b.dev网站
  • Diamond基础2:开发流程之LedDemo
  • c_str()函数的详细解析
  • 简单的 VSCode 设置
  • (nice!!!)(LeetCode 每日一题) 837. 新 21 点 (动态规划、数学)
  • bash shell 入门
  • 云智智慧停充一体云-allnew全新体验-路内停车源码+路外停车源码+充电桩源码解决方案
  • Rust:DLL 输出对象的生命周期管理
  • API生命周期10阶段
  • 原子操作及基于原子操作的shared_ptr实现
  • Baumer高防护相机如何通过YoloV8深度学习模型实现工作设备状态的检测识别(C#代码UI界面版)
  • 【C++】Windows 下 TCP接口超详介绍,如何实现一个TCP服务端和客户端
  • Windows 10共享打印机操作指南
  • 业务员手机报价软件免费领取——仙盟创梦IDE
  • 精美UI的单页网盘资源分享搜索页面 短剧搜索 自适应页面
  • 飞算JavaAI赋能高吞吐服务器模拟:从0到百万级QPS的“流量洪峰”征服之旅
  • IC验证 AHB-RAM 项目(一)——项目理解
  • AOP配置类自动注入
  • Git安装使用
  • Java增强for循环(小白友好版)
  • 整体设计 之“凝聚式中心点”原型 --整除:智能合约和DBMS的深层联合 之1
  • 【R语言】R语言矩阵运算:矩阵乘除法与逐元素乘除法计算对比