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

【落羽的落羽 C++】vector

在这里插入图片描述

文章目录

  • 一、vector类介绍
  • 二、vector中的常用接口
  • 三、迭代器失效问题
  • 四、vector的使用实例
  • 五、vector模拟实现

一、vector类介绍

vector是STL中的一种容器,本质上是顺序表。它和string类的结构很相似,其也有size、capacity、数组等,不同的是string底层只是字符数组,而vector类的底层是可以存储所有数据类型的数组。有了string的经验,我们理解vector就更轻松了。

vector实际上是一个类模板,在使用时,我们需要根据实际要存储的数据类型用<>表明,如vector<int> v1; vector<char> v2; vector<string> v3;等等

tip:vector<char>string看起来似乎没什么区别,但是string会在字符串后自动加\0,而前者不会,同时string中也有一些针对字符串的特殊操作也是vector中没有的。实际中根据我们的需求来选择使用。

二、vector中的常用接口

vector的接口和string中几乎完全一样,使用方法也类似,就简单介绍一下:

vector成员接口说明
size获取数据个数
capacity获取空间容量大小
resize改变vector的size
reserve改变vector的capacity
begin获取第一个数据的迭代器iterator/const_iterator
end获取最后一个数据的下一个位置的迭代器iterator/const_iterator
push_back尾部插入数据
pop_back尾部删除数据
insert插入数据
erase删除数据
swap交换两个vector的数据空间
operator[]使能像数组一样访问vector存储的数据

简单演示:
在这里插入图片描述

三、迭代器失效问题

迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际上就是一个指针,或者是对指针进行了封装,比如vector<T>的迭代器就是原生态指针T*。因此迭代器失效就是迭代器底层对应指针所指向的空间被销毁了,类似野指针的道理,使用可能会造成程序崩溃。对于vector,可能会导致其迭代器失效的操作有:resize、reserve、insert、assign、push_back,这些操作可能会进行扩容操作,vector底层旧空间被释放而开辟了一块新空间,则指向旧空间的迭代器就失效了。因此,在以上操作完成之后,如果还想要通过迭代器操作vector中的元素,需要给迭代器重新赋值。举个例子:

#include<iostream>
#include<vector>
using namespace std;
int main()
{vector<int> v = { 1, 2, 3, 4, 5 };vector<int>::iterator it = v.begin();//将有效元素个数调整至10个,多出的位置用0填充,这个操作底层会进行扩容v.resize(10, 0);//此时原来的迭代器it失效,使用程序会崩溃cout << *it;return 0;
}

在这里插入图片描述

#include<iostream>
#include<vector>
using namespace std;
int main()
{vector<int> v = { 1, 2, 3, 4, 5 };vector<int>::iterator it = v.begin();//将有效元素个数调整至10个,多出的位置用0填充,这个操作底层会进行扩容v.resize(10, 0);//此时原来的迭代器it失效,使用程序会崩溃//cout << *it;//给it重新赋值就能解决it = v.begin();while(it != v.end()){cout << *it << ' ';it++;}cout << endl;return 0;
}

在这里插入图片描述
除此之外,erase操作也会导致迭代器失效,erase删除pos位置数据后,pos位置之后的元素会往前挪动,没有造成底层空间的改变,理论上迭代器不会失效。但是如果pos位置刚好是最后一个数据,删完之后pos刚好是end的位置,而end位置是没有数据的,那么pos就失效了。因此在VS下,只要使用erase操作后,VS就认为该位置迭代器失效了。解决办法也是一样,重新赋值。

VS对迭代器失效的检查比较严格,程序会直接崩溃。而Linux下g++编译器对迭代器失效的检测较为宽松,程序可能可以运行,但是结果也会出错。

在这里插入图片描述

四、vector的使用实例

力扣题目:杨辉三角
杨辉三角想必大家都不陌生,如果想要生成杨慧三角的前numRows行,用vector来实现就很方便了,我们可以定义出vector<vector<int>>的结构,表示它存储的数据类型是vector<int>,模拟出杨辉三角的结构:
在这里插入图片描述

vector<vector<int>> generate(int numRows) 
{vector<vector<int>> vv;vv.resize(numRows);//将每一个元素都初始化成1for(int i = 0; i < vv.size(); i++){vv[i].resize(i+1, 1);}//遍历赋值for(int i = 2; i < numRows; i++){for(int j = 1; j < i; j++){vv[i][j] = vv[i-1][j] + vv[i-1][j-1];}}return vv;
}

结果没有问题
在这里插入图片描述

五、vector模拟实现

在我的vector.h中:

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace lydly
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}vector(){}vector(size_t n, const T& val = T()){reserve(n);for (size_t i = 0; i < n; i++){push_back(val);}}//利用迭代器区间构造template<class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);first++;}}//使我们可以用{}初始化vector(initializer_list<T> il){reserve(il.size());for (auto& e : il){push_back(e);}}vector(const vector<T>& v){reserve(v.capacity());for (auto& e : v){push_back(e);}}//利用std库中的swap算法void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);}vector<T>& operator=(vector<T> v){swap(v);return *this;}~vector(){if (_start){delete[] _start;_start = _finish = _end_of_storage = nullptr;}}size_t capacity() const{return _end_of_storage - _start;}size_t size() const{return _finish - _start;}T& operator[](size_t i){assert(i < size());return _start[i];}void resize(size_t n, T val = T()){if (n > size()){reserve(n);}while (_finish != _start + n){*_finish = val;_finish++;}}void reserve(size_t n){if (n > capacity()){size_t old_size = size();T* tmp = new T[n];if (_start){//深拷贝for (size_t i = 0; i < old_size; i++){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + old_size;_end_of_storage = _start + n;}}void push_back(const T& x){if (_finish == _end_of_storage){size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);}*_finish = x;_finish++;}void pop_back(){assert(_finish > _start);_finish--;}iterator insert(iterator pos, const T& x){assert(pos >= _start && pos <= _finish);if (_finish == _end_of_storage){size_t len = pos - _start;size_t newcapacity = capacity() == 0 ? 4 : capacity * 2;reserve(newcapacity);pos = _start + pos;}//pos后的数据往后挪一个位置iterator it = _finish - 1;while (it >= pos){*(it + 1) = *it;it--;}*pos = x;_finish++;return pos;}iterator erase(iterator pos){assert(pos >= _start && pos < _finish);//pos后的数据往前挪一个位置iterator it = pos + 1;while (it < _finish){*(it - 1) = *it;it++;}_finish--;return pos;}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;};
}

简单测试:
在这里插入图片描述
在这里插入图片描述

本篇完,感谢阅读。

http://www.xdnf.cn/news/153379.html

相关文章:

  • 算法习题-力扣446周赛题解
  • 通过门店销售明细表用Python Pandas得到每月每个门店的销冠和按月的同比环比数据
  • 搜广推校招面经八十二
  • Springboot集成SSE实现消息推送+RabbitMQ解决集群环境下SSE通道跨节点事件推送问题
  • 计算机网络 | Chapter1 计算机网络和因特网
  • CANape与MATLAB数据接口技术详解
  • Java进阶--面向对象设计原则
  • 基于html-css-js的尚有选页面源码详细
  • 如何解决IDE项目启动报错 error:0308010C:digital envelope routines::unsupported 问题
  • 图论---LCA(倍增法)
  • 从新手到高手:小程序开发进阶技巧分享
  • SQL 查询进阶:WHERE 子句与连接查询详解
  • Myweb项目——面试题总结
  • 多模态大语言模型arxiv论文略读(四十二)
  • ZYNQ笔记(十四):基于 BRAM 的 PS、PL 数据交互
  • Pygame字体与UI:打造游戏菜单和HUD界面
  • 【含文档+PPT+源码】基于Django的新闻推荐系统的设计与实现
  • 第八部分:缓解 RAG 中的幻觉
  • 认识哈希以及哈希表的模拟实现
  • 嵌入式硬件开发工具---万用表---示波器---仿真器
  • 解构与重构:“整体部分”视角下的软件开发思维范式
  • Dify框架面试内容整理-Dify框架
  • 学习设计模式《六》——抽象工厂方法模式
  • 大数据模型现状分析
  • 4.25test
  • 2025蓝桥省赛c++B组第二场题解
  • 在WSL2+Ubuntu22.04中通过conda pack导出一个conda环境包,然后尝试导入该环境包
  • WPF与C++ 动态库交互
  • 职业教育新形态数字教材的建设与应用:重构教育生态的数字化革命
  • 文件操作及读写-爪哇版