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

C++入门篇8---vector

vecctor是动态顺序表

一、了解vector的相关接口及其功能

1.构造函数相关接口

函数声明功能介绍
vector()无参构造
vector(size_type n,const value_type& val=value_type())构造并初始化n个val
vector(const value& x)拷贝构造
vector(InputIterator first, InputIterator last)使用迭代器进行构造

上面不认识的类型如size_type、value_type等都是被typedef过的,可以根据英文意思直接理解,或者找相关的文档进行查询

void test1()
{vector<int> v;for (auto x : v){cout << x << " ";}cout << endl;vector<int> v1(5, 2);for (auto x : v1){cout << x << " ";}cout << endl;vector<int> v2(v1);//vector<int> v2(v1.begin(),v1.end());和上一行代码等价for (auto x : v2){cout << x << " ";}cout << endl;string s = "hello world";vector<char> v3(s.begin(), s.end());//不同类型的迭代器也能初始化for (auto x : v3){cout << x << " ";}cout << endl;
}

2.vector iterator的使用

iterator的使用接口说明
begin()+end()获取第一个数据位置的iterator/const_iterator,获取最后一个数据的下一个位置的iterator/const_iterator
rbegin()+rend()获取第一个数据位置的reverse_iterator/const_reverse_iterator,获取最后一个数据的下一个位置的reverse_iterator/const_reverse_iterator
void test2()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);vector<int>::iterator it = v.begin();//注意如果写类型名,那么一定要写正确,如加不加reverse、const一定要写对//如果不想写这么长的类型,可以写auto自动类型推导while (it != v.end()){cout << *it << " ";it++;}cout << endl;vector<int>::reverse_iterator it1 = v.rbegin();while (it1 != v.rend()){cout << *it1 << " ";it1++;}cout << endl;
}

 3.vector空间增长问题

函数名称接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize改变vector的size
reserve改变vector的capacity
void test3()
{vector<int> v;cout << v.size() << endl;cout << v.capacity() << endl;cout << v.empty() << endl;cout << "----------" << endl;vector<int> v1(5, 2);cout << v1.size() << endl;cout << v1.capacity() << endl;cout << v1.empty() << endl;cout << "----------" << endl;//vector<int> v2(v1);vector<int> v2(v1.begin(),v1.end());cout << v2.size() << endl;cout << v2.capacity() << endl;cout << v2.empty() << endl;cout << "----------" << endl;string s = "hello world";vector<char>v3(s.begin(), s.end());cout << v3.size() << endl;cout << v3.capacity() << endl;cout << v3.empty() << endl;
}

 结论:构造函数创建对象时,有多少个数据开多少空间

void test4()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };int n = sizeof(arr) / sizeof(int);vector<int> v(arr, arr + n);//vector迭代器本质就是指针,所以这里传指针没问题cout << v.size() << ":" << v.capacity() << endl;v.reserve(100);v.resize(20);cout << v.size() << ":" << v.capacity() << endl;v.reserve(50);v.resize(5);cout << v.size() << ":" << v.capacity() << endl;
}

 结论:resize控制size()的大小,空间不够会扩容,reserve申请预留的空间如果小于已经开出的空间capacity(),则空间大小不变,如果大于,则会扩容(至于扩多大的容,主要看编辑器,但是至少保证空间够用)

4.vector的增删查改

函数名称接口说明
push_back()尾插
pop_back()尾删
find查找(vector没有find成员函数,这个find是算法库中的),如果找到find
insert在pos之前插入val,返回新插入元素位置的迭代器
erase删除pos位置的数据,返回被删除元素的下一个元素位置的迭代器
swap交换两个vector的数据空间
operator[]像数组一样用下标访问数据
void test6()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);for (int i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;v.pop_back();for (int i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;v.insert(v.begin() + 1, 10);for (int i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;v.erase(v.begin() + 2);for (int i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;auto itx = find(v.begin(), v.end(), 10);//返回迭代器if (itx != v.end())//没找到返回end()cout << *itx;
}

 5.迭代器失效(重点)

由于vector的迭代器底层是指针,所以vector迭代器失效本质就是野指针问题

对于vector可能会导致其迭代器失效的操作有

1.在插入元素的过程中,导致扩容,而导致原本的空间被释放,那么在扩容之前获取的迭代器就会失效(这是一个例子,其实只要引发扩容,都可能导致迭代器失效)

2.删除操作,一般来说删除元素不会出现问题,但是如果删除的元素是最后一个元素,那么最后一个元素(即被删除元素位置)的迭代器就会失效

如果没看懂的,可以看看后面对插入删除功能的模拟实现)

以下代码的功能是删除vector中所有的偶数,请问while循环的代码是正确的

void test7()
{vector<int> v{ 1, 2, 3, 4 };auto it = v.begin();while (it != v.end()){if (*it % 2 == 0)v.erase(it);++it;}while (it != v.end()){if (*it % 2 == 0)v.erase(it);else++it;}while (it != v.end()){if (*it % 2 == 0)it = v.erase(it);else++it;}
}

很显然第一个while循环错误,因为删除是将后面的元素整体往前移动,所以删除完成之后,it就已经指向了后一个元素,不需要++,

而第二个while循环逻辑上没有问题,但是不同的编辑器会有不同的结果,在vs上,编辑器会严格检查在可能导致迭代器失效的操作之后使用之前的迭代器,直接报错,而在g++上就不会报错

第三个while循环才是标准的写法,而这也是对迭代器失效问题的解决---为erase函数设置了返回值,返回删除元素后面一个元素的迭代器,这样就确保不会发生迭代器失效的问题了

二、模拟实现vector的基本功能

namespace zxws
{template<class T>class vector{public:// Vector的迭代器是一个原生指针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(int n, const T& value = T()){reserve(n);while (n--) {push_back(value);}}template<class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);first++;}}vector(const vector<T>& v){reserve(v.capacity());for (auto& x : v){push_back(x);}}vector<T>& operator= (vector<T> v){swap(v);return *this;}~vector(){if (_start){delete[] _start;_start = _finish = _endOfStorage = nullptr;}}// capacitysize_t size() const{return _finish - _start;}size_t capacity() const{return _endOfStorage - _start;}void reserve(size_t n){if (n > capacity()){size_t sz = size();T* tmp = new T[n];if (_start){for (size_t i = 0; i < sz; i++){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + sz;_endOfStorage = _start + n;}}void resize(size_t n, const T& value = T()){if (n > size()){reserve(n);for (size_t i = size(); i < n; i++){_start[i] = value;}}_finish = n + _start;}T& operator[](size_t pos){assert(pos < size());return _start[pos];}const T& operator[](size_t pos)const{assert(pos < size());return _start[pos];}void push_back(const T& x){if (_finish == _endOfStorage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;_finish++;}void pop_back(){assert(size() > 0);_finish--;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endOfStorage, v._endOfStorage);}iterator insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);if (_finish == _endOfStorage){size_t l = pos - _start;reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _start + l;}iterator it = _finish;while (it > pos){*it = *(it - 1);--it;}*pos = x;_finish++;return pos;}iterator erase(iterator pos){assert(pos >= _start);assert(pos < _finish);iterator it = pos;while (it < _finish - 1){*it = *(it + 1);it++;}_finish--;return pos;}private:iterator _start = nullptr;// 指向数据块的开始iterator _finish = nullptr; // 指向有效数据的尾iterator _endOfStorage = nullptr; // 指向存储容量的尾};void test(){//vector<int> v;vector<int> v(10);vector<int> v(10,2);//v.push_back(1);//v.push_back(2);//v.push_back(3);//v.push_back(4);//for (auto x : v)//{//    cout << x << " ";//}//cout << endl;//vector<int>v1(v);//for (auto x : v1)//{//    cout << x << " ";//}//cout << endl;string s = "hello world";vector<char> s1(s.begin(), s.end());for (auto x : s1){cout << x << " ";}cout << endl;vector<char> s2;s2 = s1;for (auto x : s2){cout << x << " ";}cout << endl;}void test1(){vector<string>v;v.push_back("11111111");v.push_back("11111111");v.push_back("11111111");v.push_back("11111111");v.push_back("11111111");v.push_back("11111111");v.push_back("11111111");v.push_back("11111111");v.push_back("11111111");for (auto x : v){cout << x << " ";}cout << endl;}void test2(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(2);v.push_back(3);v.push_back(4);vector<int>::iterator it = v.begin();while(it!=v.end()){if (*it % 2 == 0)it = v.erase(it);elseit++;}for (auto x : v){cout << x << " ";}cout << endl;v.pop_back();for (auto x : v){cout << x << " ";}cout << endl;}void test3(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);v.insert(v.begin()+2, 0);v.insert(v.end(),0);for (auto x : v){cout << x << " ";}cout << endl;}
}

相关文章:

C++入门篇8---vector

vecctor是动态顺序表 一、了解vector的相关接口及其功能 1.构造函数相关接口 函数声明功能介绍vector()无参构造vector(size_type n,const value_type& valvalue_type())构造并初始化n个valvector(const value& x)拷贝构造vector(InputIterator first, InputIterato…...

【学会动态规划】最大子数组和(19)

目录 动态规划怎么学&#xff1f; 1. 题目解析 2. 算法原理 1. 状态表示 2. 状态转移方程 3. 初始化 4. 填表顺序 5. 返回值 3. 代码编写 写在最后&#xff1a; 动态规划怎么学&#xff1f; 学习一个算法没有捷径&#xff0c;更何况是学习动态规划&#xff0c; 跟我…...

怎么做Tik Tok海外娱乐公会呢?新加坡市场怎么样?

一、为什么选择TikTok直播 1. 海外市场潜力巨大 • 自2016年始&#xff0c;多家直播平台陆续拓展至东南亚、中东、俄罗斯、日韩、欧美、拉美等地区。 • 海外市场作为直播发展新蓝海&#xff0c;2021年直播行业整申请cmxyci体规模达百亿美元&#xff0c;并维持高速增长。 &a…...

mysql主从复制搭建

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言MySQL复制过程分为三部&#xff1a; 一、准备工作二、配置>主库Master三、配置>从库SlaveSlave_IO_Running: YesSlave_SQL_Running: Yes 四、测试至此&am…...

Java:正则表达式案例:爬数据,重复数据替换,数据分割

使用正则表达式查找一段文本中的内容 需求:请把下面文本中的电话&#xff0c;邮箱&#xff0c;座机号码&#xff0c;热线都爬取出来。 String data "电话:1866668888&#xff0c;18699997777\n" "或者联系邮箱: boniuitcast.cn&#xff0c;\n" "座机…...

CF 765D Artsem and Saunders 构造

CF765D Artsem and Saunders 直接猜一种构造做法&#xff0c; h ( x ) h(x) h(x)的值域一定和 f ( x ) f(x) f(x)的值域一样&#xff0c;我们先满足 h ( g ( x ) ) f ( x ) h(g(x))f(x) h(g(x))f(x)这个条件&#xff0c;遍历 f ( x ) f(x) f(x)&#xff0c;每次添加 h ( x ) h…...

DevOps系列文章 之 SpringBoot整合GitLab-CI实现持续集成

在企业开发过程中&#xff0c;我们开发的功能或者是修复的BUG都需要部署到服务器上去&#xff0c;而这部分部署操作又是重复且繁琐的工作&#xff0c;GitLab-CI 持续集成为我们解决了这一痛点&#xff0c;将重复部署的工作自动化&#xff0c;大大的节省了程序员们的宝贵时间。本…...

K8S系列二:实战入门

I. 配置kubectl 1.1 什么是kubectl&#xff1f; 官方文档中介绍kubectl是&#xff1a; Kubectl 是一个命令行接口&#xff0c;用于对 Kubernetes 集群运行命令。Kubectl的配置文件在$HOME/.kube目录。我们可以通过设置KUBECONFIG环境变量或设置命令参数–kubeconfig来指定其他…...

form中表单切换,导致 relus 中的事件无法触发,原因:页面切换不要一直切换DOM,会导致问题,需要都显示出来

修改前&#xff0c;因为重复渲染DOM导致绑定rules失效 修改前代码使用 computed 计算出渲染的DOM&#xff0c;影响rules事件<el-formref"form"inline:model"billDetailCopy":rules"rules"size"small"label-position"right&quo…...

Android Ble蓝牙App(五)数据操作

Ble蓝牙App&#xff08;五&#xff09;数据操作 前言正文一、操作内容处理二、读取数据① 概念② 实操 三、写入数据① 概念② 实操 四、打开通知一、概念二、实操三、收到数据 五、源码 前言 关于低功耗蓝牙的服务、特性、属性、描述符都已经讲清楚了&#xff0c;而下面就是使…...

.netcore grpc双向流方法详解

一、双向流处理概述 简单来讲客户端可以向服务端发送消息流&#xff0c;服务端也可以向客户端传输响应流&#xff0c;即客户端和服务端可以互相通讯客户端无需发送消息即可开始双向流式处理调用 。 客户端可选择使用 RequestStream.WriteAsync 发送消息。 使用 ResponseStream…...

【Servlet】(Servlet API HttpServlet 处理请求 HttpServletRequest 打印请求信息 前端给后端传参)

文章目录 Servlet APIHttpServlet处理请求 HttpServletRequest打印请求信息前端给后端传参 Servlet API Servlet中常用的API HttpServlet 实际开发的时候主要重写 doXXX 方法, 很少会重写 init / destory / service destory 服务器终止的时候会调用. //下面的注解把当前类和…...

java中右移>>和无符号右移>>>的区别

public static void main(String[] args) {byte[] dest new byte[2];dest[0] 0x15; //0001 0101dest[1] (byte) 0xfb;//1111 1011System.out.println((dest[0] >> 4) & 0xff);//右移 应该是0000 0001 十进制结果显示1 结果也是1&#xff0c;正确System.out.printl…...

牛客周赛 Round 7

目录 A 游游的you矩阵 题目&#xff1a; 题解&#xff1a; AC 代码&#xff1a; B 游游的01串操作 题目&#xff1a; 题解&#xff1a; AC 代码&#xff1a; C 游游的正整数 题目&#xff1a; 题解&#xff1a; AC 代码&#xff1a; D 游游的选数乘积 题目&#xf…...

R语言生存分析(机器学习)(1)——GBM(梯度提升机)

GBM是一种集成学习算法&#xff0c;它结合了多个弱学习器&#xff08;通常是决策树&#xff09;来构建一个强大的预测模型。GBM使用“Boosting”的技术来训练弱学习器&#xff0c;这种技术是一个迭代的过程&#xff0c;每一轮都会关注之前轮次中预测效果较差的样本&#xff0c;…...

k8s和docker简单介绍

当涉及到容器技术和容器编排时&#xff0c;Docker和Kubernetes是两个重要的概念。我将更详细地介绍它们以及它们之间的关系。 Docker&#xff1a; Docker是一种容器化技术&#xff0c;它允许你将应用程序及其依赖项打包到一个称为"容器"的封闭环境中。每个容器都包…...

Lua学习记录

Lua基础了解 Lua的注释通过 (-- 单行注释&#xff0c;--[[ ]] 多行注释)可以不加&#xff1b; 多个变量赋值&#xff0c;按顺序赋值&#xff0c;没有则为nil&#xff1b; function的简单用法&#xff0c;多个返回值配合多重赋值&#xff0c;以end为结束标志 Lua下标从1开始&…...

三分钟完美解决你的C盘内存过大爆红

一、清理回收站 二、清理桌面 建议一 不要在桌面放太多图标或者文件会占用过多的内存,可以放到其他盘建议二、 将位置移动到别的盘 三、手动删除下载文件与缓存文件 日常使用中会通过Windows下载各种文件资料到电脑中&#xff0c;它默认也是直接下载在C盘中的。如果我们在以…...

C++ - equal(比较两个vector元素)

C标准库的std::equal函数。这个函数用于比较两个范围的元素是否相等。 在使用std::equal函数时&#xff0c;您需要提供两个范围的迭代器&#xff0c;以及一个可选的谓词函数&#xff08;predicate&#xff09;。函数会比较第一个范围内的元素和第二个范围内的元素是否相等。如果…...

多线程:线程池

线程池 提前创建多个线程放入线程池中&#xff0c;使用时直接获取&#xff0c;使用完直接放入池中&#xff1b;可以避免频繁创建销毁&#xff0c;实现重复利用&#xff0c;类似生活中的公共交通工具。好处&#xff1a;提高相应速度&#xff1b;降低资源消耗&#xff1b;便于线…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

【SpringBoot自动化部署】

SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一&#xff0c;能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时&#xff0c;需要添加Git仓库地址和凭证&#xff0c;设置构建触发器&#xff08;如GitHub…...

规则与人性的天平——由高考迟到事件引发的思考

当那位身着校服的考生在考场关闭1分钟后狂奔而至&#xff0c;他涨红的脸上写满绝望。铁门内秒针划过的弧度&#xff0c;成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定"&#xff0c;构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...