C++中的vector使用与实现

news2024/10/23 20:16:48

一、vector的使用

1.1 vector的定义

是一种类模板

template < class T, class Alloc = allocator<T> > 
class vector;

其中的模板参数Alloc是在使用空间配置器(内存池),并给了缺省值,暂时不深究

1.2遍历方式

1.2.1下标+[]遍历

与sting类似,得益于其物理连续结构

1.2.2迭代器遍历

在书写迭代器类型的时候要注意加上模板类型

vector<int>::iterator it1=v1.begin();
1.2.2补:string也可以放到模板里

对应类型vector<string>

此时若要尾插一个string可以用上匿名对象的方法

如要尾插一个:

//①
string s1("张三");
v1.push_back(s1);

//②
v1.push_back(string("李四"));

//③
v1.push_back("王五");

这里的②就是用了匿名对象,而③用了单参数构造函数的隐式类型转换加匿名对象。

1.2.3范围for遍历

普通类型的用法与string类似,但是string的话最好

for(const string& e:v)
{//...}

这样可以避免string频繁地进行深拷贝,消耗时间

1.3数据的控制

1.3.1插入删除的操作

使用push_back和pop_back来完成,头插头删需要配合insert和erase来使用

void push_back (const value_type& val);

void pop_back();

iterator insert (iterator position, const value_type& val);

iterator erase (iterator position);

1.3.2resize的操作

比原来短就缩小,比原来长就默认补齐,这里填补的数字有缺省值,可以选择补默认的(如0)或者自行指定

void resize (size_type n, value_type val = value_type());

1.4顺序表的嵌套

即顺序表的顺序表,如

vector<vector<int>>

此时顺序表中存的就是一个个地址,访问的时候可以采用类似二维数组的访问方式

vv[i][j];

//实质上是
vv.operator[](i).operator[](j);

1.5顺序表常常配合算法sort使用,但排序的方式可能是自定义类型,怎么解决?

sort添加了一个重载,这个重载中有第三个参数

Compare comp

这是一种仿函数的应用,我们只要知道默认排升序,如果要改降序可以采用这一操作:

greater<int> gt;
sort(s1.begin(),s1.end(),gt);

greator这一模板属于std库,于它对应的还有一个less,传过去可以排升序。

二、vector的实现

2.1实现时的分文件问题

对于模板的声明与定义分离我们需要准备多行代码,因此建议都在一个文件.h中实现

2.1补:阅读源码的过程

①先看成员变量

②再看核心成员函数,如构造函数,vector中的尾插等等

③大致了解以后再展开看

2.2reserve实现时的陷阱

我们实现vector的时候有三个成员变量

_start      _finish      _end_of_storage

分别存储   初始位置,最后一个元素下一个位置,当前空间结束的下一个位置   三处的迭代器

size依靠指针相减得出大小,因此申请新空间以后size()会失效,需要提前记录size的大小方便使用。

2.3vector中的find问题

vector不再提供find,而是在算法algorithm头文件下有find函数来让stl统一使用。

2.4insert与erase涉及到的迭代器失效问题

2.4.1insert中

迭代器失效是扩容导致的,在插入时扩容后,_start和_finish会转移到新空间,那么原来标识插入位置的参数pos就会失效

直接在参数列表加引用可不可以?

答:不可以,例如当我们调用函数的语句写为

v1.insert(v1.begin(),0);

这样的时候,因为begin()是传值返回,而传值返回意味着会进行拷贝生成临时对象,临时对象具有常性,不可被修改

为此,我们以iterator作为返回值,出现类似

it=v1.insert(it,0);

这样的形式,更新一下it对应的迭代器。

2.4.2erase中

因为有时会erase最后一个数据,造成野指针,所以我们统一认为pos位置迭代器已失效,在VS中会在类型层面对它标识,不允许访问;在Linux中没有进行强制处理

此时我们的解决方案依旧是iterator作为返回值,更新一下来去除标识

2.4.2补:Linux中隐藏的陷阱

虽然在Linux中没有进行强制处理,但是也不能抱有侥幸心理,因为可能出现野指针问题和其他编译器无法运行的问题。

2.5实现拷贝构造时的问题

在自行实现vector的时候我们习惯直接用默认构造函数,但是因为拷贝构造也属于一种构造,所以在显示写完拷贝构造以后,编译器不会默认生成构造函数,这时可以用

2.5补:default关键字

vector()=default;

可以强制生成默认构造函数。

2.6迭代器区间进行构造中的问题

类模板的成员函数也可以写成函数模板,这里我们就用到了这一说法

template <class InputIterator>
         vector (InputIterator first, InputIterator last,
                 const allocator_type& alloc = allocator_type());

我们之所以要写成函数模板,就是为了可以支持所有类型的迭代器进行区间初始化,它的实现逐步尾插即可

2.7缺省值T()与C++对内置类型的更新

对于泛型编程来说,有时我们需要给一种缺省值:来达到模板类型是什么,就给什么类型的值这一效果,为此出现了T(),

如vector的一种特殊构造:用n个val初始化vector就用到了

explicit vector (size_type n, const T& val = T(),
                 const allocator_type& alloc = allocator_type());

其中,T()本质是自动调用构造函数,自定义类型完美解决,可是这样一来内置类型也需要构造了

2.7补:内置类型的构造

其实就是简单的赋值,如以下几种写法:

int a1=0;
int a2(1);
int a3=int();
int a4=int(1);

分别赋值0,1,0,1

2.8 vector(size_t n,const T& value)与vector(int n,const T& value)同时存在的原因

因为函数调用的冲突问题,

template <class InputIterator>
         vector (InputIterator first, InputIterator last);
                 

vector (size_type n, const T& val = T())
                

同时存在的时候,我们的代码(int类型的特殊问题)

vector<int> v1(10,1);

本意是用10个1来初始化,却被上面的模板读取导致目的无法达到,因此重载一个函数来避免这种“抢调用”的情况。

2.9C++中{}的问题(initializer_list列表构造vector)

{}的功能不少,有

//多参数的隐式类型转换
A aa1={1,2};

//单参数也可以用{}来隐式类型转换
B aa2={1};

要区分

std::vector<int> v1={1,2,3,4,5,6};

这里的隐式类型转换因为参数个数不固定,与上面不同,隐式类型转换到的新类型是属于C++11新支持的initializer_list类型

它有两种表示方法:

auto li={1,2,3,4,5,6};


initializer_list<int> li={1,2,3,4,5,6};

此处li的类型为initializer_list

要想支持上述v1的顺利构造,需要写一个传参为initializer_list<T>类型的构造函数

库中:

vector (initializer_list<value_type> il,
       const allocator_type& alloc = allocator_type());

之后如

vector<int> v1({1,2,3});

vector<int> v2={10,20,30};

都可以支持了。

2.10关于reverse对于含有资源管理的自定义类型的拷贝

对于内置类型和无资源管理的自定义类型,我们在实现reverse的时候进行memcpy对应的浅拷贝即可,但是对于如string类型的含有资源管理的自定义类型,我们在需要申请空间的时候会进行浅拷贝,delete销毁会导致原空间内容一并销毁,导致析构多次。

为此我们可以用下标+[]循环赋值来深拷贝解决。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2221842.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电商大数据获取渠道分享--官方接口、爬虫、第三方如何选择?

在当今大数据驱动的商业环境中&#xff0c;电商企业越来越依赖数据分析来洞察市场、优化运营和提升竞争力。本文将分享几种常见的电商大数据获取渠道&#xff0c;帮助电商从业者更有效地收集和利用数据资源。 一、电商平台官方接口 各大电商平台如淘宝、京东、拼多多等&#…

DML语言

DML&#xff08;数据操作语言&#xff09; 用于操作数据库对象中所包含的数据 包括&#xff1a; INSERT ( 添加数据语句 ) UPDATE ( 更新数据语句 ) DELETE ( 删除数据语句 ) INSERT ( 添加数据语句 ) INSERT INTO 表名 [ ( 字段1, 字段2, 字段3, … ) ] VALUES ( 值1, 值2,…

计算机网络-RSTP工作过程与原理

前面我们已经学习了RSTP的一些基础概念以及对于STP的改进之处&#xff0c;因为RSTP兼容STP&#xff0c;所以实际上两者工作原理是一致的&#xff0c;这里只简单过一遍&#xff0c;然后进行一些基础实验即可&#xff0c;大致还是遵循选举根桥、确定端口角色与状态、全网收敛的思…

CentOS 8 Stream环境下通过yum安装Mysql

1.在Mysql下载页面MySQL :: Download MySQL Community Server页尾 点击 “MD5 checksums and GnuPG signatures” 进入下一页面 2.打开下载yum repo文件页面 (MySQL :: Download MySQL Yum Repository) 3.点击"DownLoad"按钮&#xff0c;打开下载页面&#xff0c; 4.…

GB/T28181-2022规范解读、应用场景和技术实现探究

GB/T28181-2022和GB/T28181-2016区别 GB/T28181-2022《公共安全视频监控联网系统信息传输、交换、控制技术要求》与 GB/T28181-2016 相比&#xff0c;主要有以下区别&#xff1a; 术语和定义方面&#xff1a; 术语删减&#xff1a;GB/T28181-2022 删除了 “联网系统信息”“数…

大模型LLM学习路线图2024年最新版!全面掌握学习路径,非常详细,零基础想学大模型收藏这一篇就够了

ChatGPT的出现在全球掀起了AI大模型的浪潮&#xff0c;2023年可以被称为AI元年&#xff0c;AI大模型以一种野蛮的方式&#xff0c;闯入你我的生活之中。 从问答对话到辅助编程&#xff0c;从图画解析到自主创作&#xff0c;AI所展现出来的能力&#xff0c;超出了多数人的预料&…

【redis】redis的多线程和IO多路复用

【redis】redis的多线程和IO多路复用 【一】前言【二】Redis单线程和多线程问题的背景【1】Redis的单线程【2】Redis为什么选择单线程&#xff1f;【3】Redis为什么开始利用多核&#xff1f;【4】Redis当前的性能瓶颈【5】Redis的主线程如何和IO线程协同 【三】IO多路复用的理解…

【Trick】IOS系统解决“未受信任的企业级开发者”问题

问题&#xff1a; 本人通过扫码下载了一个软件&#xff0c;下载完毕后出现以下提示&#xff1a; 解决方法&#xff1a; 这个主要是操作系统的问题&#xff0c;需要在设置里面更改&#xff0c;具体步骤如下&#xff1a; 【1】打开设置&#xff0c;选择【通用】 【2】选择【VP…

千鹿 AI ——AI一键生成模特上身图,零成本制作服装电商图片,AI换模特/背景/批量抠图,一个网站就够了!

前言 在电商行业&#xff0c;卖产品主要是卖图片。拍一套产品图加上美工费用&#xff0c;基本要大几百上千&#xff0c;对新手卖家是不小的支出。服装类目的 SKU 很多&#xff0c;一个链接下有几十个款式很常见。 AI 出现对跨境电商有好处是大家都知道的。现在看看电商领域的…

rust aarch64开发-编译

1. 实验代码下载 本实验基于github或gitee上的开源实现。 // 无法访问github可以通过如下地址下载 git clone https://gitee.com/yang_jun_yi/armv8-rust-hypervisor.git // github下载 git clone https://github.com/Comet959/armv8-rust-hypervisor.git2. 编译 make start…

PG实践|数学函数及其操作(一)

文章目录 引言1.1 ABS() - 取绝对值1.2 CEIL() 或 CEILING() - 向上取整1.3 FLOOR() - 向下取整1.4 ROUND() - 四舍五入1.5 TRUNC() - 截断/截取小数总结 &#x1f4eb; 作者简介&#xff1a;「六月暴雪飞梨花」&#xff0c;专注于研究Java&#xff0c;就职于科技型公司后端工程…

Spring配置/管理bean-IOC(控制反转) 非常详细!基于XML及其注解!案例分析! 建议复习收藏!

目录 1.Spring配置/管理bean介绍 2.基于XML配置bean 2.1基于id来获取bean对象 2.2基于类型获取bean对象 2.3通过指定构造器配置bean对象 2.4通过p名称空间配置bean 2.5通过ref配置bean(实现依赖注入) 2.6注入内部Bean对象&#xff0c;依赖注入另一种方式 2.7 注入集合…

AWD的复现

学习awd的相关资料&#xff1a;速成AWD并获奖的学习方法和思考记录- Track 知识社区 - 掌控安全在线教育 - Powered by 掌控者&#xff08;包含使用脚本去批量修改密码&#xff09; 在复现之前去了解了以下AWD的相关脚本 资料&#xff1a;AWD批量攻击脚本使用教程-CSDN博客 …

网络安全有关法律法规

1. 前言 在当今数字化高速发展的时代&#xff0c;网络安全已成为关乎国家、企业和个人的重要议题。为了应对日益复杂的网络安全挑战&#xff0c;一系列网络安全法律法规应运而生&#xff0c;它们如同坚实的盾牌&#xff0c;守护着我们的数字世界。现在是2024年10月&#xff0c…

军团服务QA角度总结

需求背景&#xff1a; 军团业务诞生的时候承接家族群组功能&#xff0c;玩法邀请成员做任务->积分升级->发送奖励。还是拉收入的一个业务载体。收入才是王道。 军团服务端核心就三个&#xff1a;军团创建&#xff0c;人员管理和军团奖励。 军团创建&#xff1a; 创建…

每天练打字8:今日状况——常用字后五百击键4.5第1遍进行中,赛文速度105.75

今日跟打&#xff1a;738字 总跟打&#xff1a;125701字 记录天数&#xff1a;2459天 &#xff08;实际没有这么多天&#xff0c;这个是注册账号的天数&#xff09; 平均每天&#xff1a;50字 本周目标完成进度&#xff1a; 练习常用单字后500&#xff0c;击键3.5&#xff0c;…

kernel32.dll的功能、作用,教大家几种修复kernel32.dll错误的办法

当这个文件出现问题时&#xff0c;用户可能会遇到各种错误消息&#xff0c;例如“缺失kernel32.dll”或“kernel32.dll发生错误”。这些错误不仅令人困扰&#xff0c;还可能威胁到您的数据安全和系统性能。接下来&#xff0c;本文将教大家几种修复kernel32.dll错误的有效方法&a…

群控系统服务端开发模式-业务流程图补充

进天有读者给我反馈&#xff0c;业务流程图看的不是很明确&#xff0c;所以我把未画完的业务流程图补充完毕。也希望以后更多的读者给我评论及意见。 一、业务流程梳理 1、非业务流程 a、添加部门、添加级别、添加执行方式。因为这些参数都是要被其他地方调用的&#xff0c;更…

word中的内容旋转90度

在vsto、Aspose.Words 中&#xff0c;默认没有直接的 API 可以让表格整体旋转 90 度。然而&#xff0c;我们可以通过一些方式来实现类似的效果&#xff0c;具体思路如下&#xff1a; 将表格插入到一个形状&#xff08;Shape&#xff09;或文本框中&#xff0c;然后旋转该形状。…

影刀RPA实战番外:excel函数应用指南

Excel函数是用于执行特定计算、分析和数据处理任务的预定义公式。它们可处理数学计算、文本处理、逻辑判断、日期和时间运算、查找和引用数据等。例如&#xff0c;SUM函数可以计算一系列数字的总和&#xff0c;IF函数进行逻辑测试&#xff0c;VLOOKUP函数在表格中查找数据&…