【C++初阶】第11课—vector

文章目录

  • 1. 认识vector
  • 2. vector的遍历
  • 3. vector的构造
  • 4. vector常用的接口
  • 5. vector的容量
  • 6. vector的元素访问
  • 7. vector的修改
  • 8. vector<vector\<int\>>的使用
  • 9. vector的使用
  • 10. 模拟实现vector
  • 11. 迭代器失效
    • 11.1 insert插入数据内部迭代器失效
    • 11.2 insert插入数据外部迭代器失效
    • 11.3 erase删除数据迭代器失效
  • 12. 模拟实现resize
  • 13. 模拟实现vector的拷贝构造
  • 14. 模拟实现vector的赋值操作符重载
  • 15. 模拟实现reserve存在的坑
  • 16. 模拟实现vector初始化
  • 17. vector构造时容易出现的坑
  • 18. 模拟实现vector代码

1. 认识vector

  • vector是向量、矢量的意思
  • vector其实就是数据结构阶段学过的顺序表,行为看起来像指针一样的容器,底层不一定是用指针实现的,具体根据编译器的底层实现结构为准
  • vector的使用:vector<数据类型> 对象名

在这里插入图片描述


2. vector的遍历

在这里插入图片描述


3. vector的构造

在这里插入图片描述


  • 对于vector的析构,跟string类似,它会自动调用

4. vector常用的接口

在这里插入图片描述


  • vector上述的接口与string的接口并无二异

在这里插入图片描述


  • cbegin( )和cend( )的用法与begin和end类似,无非就是常量迭代器不能改变数据而已

5. vector的容量

在这里插入图片描述


在这里插入图片描述


  • 对于判空empty和请求缩容shrink_to_fit不再过多赘述,string里面都有讲到

6. vector的元素访问

在这里插入图片描述


在这里插入图片描述


  • at和下标访问操作符[ ]都是用来访问vector内的元素,区别是越界时下标操作符[ ]会报错,而at会抛出异常,关于这点string已经讲过,后续讲到捕获异常时可重温复习以加深理解

7. vector的修改

在这里插入图片描述


在这里插入图片描述


  • 其余的像swap用来交换两个vector对象,使用时可参考官方文档,大部分与string类模版中的用法类似

8. vector<vector<int>>的使用

  • vector<vector<int>>其实就是类似二维数组的用法,使用vector实例化出int类型的对象,再使用vector<vector<int>>实例化出vector<int>的对象

在这里插入图片描述


在这里插入图片描述


#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
//vector<vector<int>>的使用(杨辉三角)
size_t numRows = 0;
cin >> numRows; //行数
vector<vector<int>> vv(numRows);
//所有数设置为1
for (size_t i = 0; i < numRows; i++)
{vv[i].resize(i + 1, 1);
}
//中间元素为上面两个元素之和
for (size_t i = 2; i < numRows; i++)
{for (size_t j = 1; j < vv[i].size() - 1; j++){vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];}
}
//打印
for (size_t i = 0; i < numRows; i++)
{//打印前面的空格for (size_t k = 0; k < numRows - i - 1; k++){cout << " ";}for (size_t j = 0; j < vv[i].size(); j++){cout << vv[i][j] << " ";}cout << endl;
}
return 0;
}

9. vector的使用

  • 对于vector容器,也可以使用string类型,其插入string类型的数据如下

在这里插入图片描述


  • 关于vector和C++算法库的一些使用,以下先作为一个了解

在这里插入图片描述


10. 模拟实现vector

  • 之前讲述过,迭代器都是左闭右开的区间,对于begin指向第一个数,而end则指向最后一个数的下个位置
  • 因此对于vector的成员变量_start和_finish、_end_of_storage来讲,_finish就是指向有效数据的下个位置,_end_of_storage就指向容量的下个位置

在这里插入图片描述


在这里插入图片描述


  • 接下主要讲reserve扩容的坑,其余较容易实现

在这里插入图片描述


  • insert在pos位置插入字符
  • 注意:pos的类型是迭代器iterator,因为vector的成员变量是iterator类型,类似迭代器begin()和end()

在这里插入图片描述


  • 对于上述insert插入数据的代码,存在一个巨大隐患:迭代器失效的问题,接下来主要讲容器中的迭代器失效的问题

11. 迭代器失效

11.1 insert插入数据内部迭代器失效

在这里插入图片描述


  • 解决上面迭代器失效的方法:扩容后更新pos

在这里插入图片描述


11.2 insert插入数据外部迭代器失效

在这里插入图片描述


  • 即使是库里面实现的vector,对于insert插入数据也会出现迭代器失效的问题
  • 迭代器失效的根本原因就是扩容,扩容前后外部迭代器指向的是旧空间,而扩容后旧空间被释放,再访问就会报错
  • 因此对于insert插入数据后外部传参的迭代器,由于不同的平台结果可能不同,统一认为该迭代器失效
  • 解决办法:insert插入数据后更新迭代器

在这里插入图片描述


11.3 erase删除数据迭代器失效

在这里插入图片描述


在这里插入图片描述


  • 解决办法:在erase删除数据后即使更新迭代器it

在这里插入图片描述


  • 总结
  • 对于迭代器失效的问题,主要存在于容器插入和删除元素时,这里以vector为例,在insert插入数据和erase删除数据后,迭代器就处于失效的状态,这是因为插入数据扩容导致以及删除数据缩容导致的一系列问题
  • 对于不同的编译器,结果可能不同,并且vs对于迭代器失效的检查尤为严格,它会对失效的迭代器进行标记,如果尝试使用这些失效的迭代器,它就会报错
  • 因此统一认为容器插入数据和删除数据后迭代器处于失效的状态
  • 如果想继续使用失效的迭代器,解决办法就是在插入数据或删除数据前后根据实际情况及时更新迭代器,使迭代器正确指向对应的数据

12. 模拟实现resize

在这里插入图片描述


在这里插入图片描述


13. 模拟实现vector的拷贝构造

在这里插入图片描述


14. 模拟实现vector的赋值操作符重载

在这里插入图片描述


15. 模拟实现reserve存在的坑

  • reserve扩容的第一个坑

在这里插入图片描述


  • reserve扩容的第二个坑

在这里插入图片描述

  • 插入前四个字符串时没有问题,但是插入第5个字符串时,为什么会出现问题呢?
  • 因为插入第5个字符串时会扩容,reserve扩容中的memcpy其实就是一个浅拷贝,之前再C语言阶段实现过memcpy这个函数,它是一个字节一个字节拷贝的
  • 参考链接:memcpy的使用和模拟实现

在这里插入图片描述


在这里插入图片描述


  • 解决方案

在这里插入图片描述


16. 模拟实现vector初始化

  • C++11提供了vector初始化列表来进行初始化

在这里插入图片描述


  • inltializer_list是C++11设置一个模版类型
  • 其用法和之前创建数组有点类似

在这里插入图片描述


在这里插入图片描述


  • C++还提供了迭代器区间初始化

在这里插入图片描述


在这里插入图片描述


  • 当然数组也可以当做迭代器使用

在这里插入图片描述


17. vector构造时容易出现的坑

  • 用n个val值构造vector对象

在这里插入图片描述


在这里插入图片描述


  • 解决措施

在这里插入图片描述


18. 模拟实现vector代码

//模版
template <class T>
class vector
{
public://迭代器typedef T* iterator;typedef const T* const_iterator;//构造函数vector(){}//初始化列表初始化vector(initializer_list<T> il){reserve(il.size());for (auto& e : il){push_back(e);}cout << "初始化列表初始化:" << endl;}//迭代器区间初始化//类模板函数的成员函数,也可以是函数模版template <class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}}//vector的构造--->n个valvector(int n, const T& val = T()){resize(n, val);}vector(size_t n, const T& val = T()){resize(n, val);}//拷贝构造 vector(const vector<T>& v){reserve(v.size());for (auto& e : v){//this->push_back(e);push_back(e);}}//有效数据sizesize_t size() const{return _finish - _start;}//容量size_t capacity() const{return _end_of_storage - _start;}//beginiterator begin(){return _start;}//enditerator end(){return _finish;}//const beginconst_iterator begin() const{return _start;}//const endconst_iterator end() const{return _finish;}//resize改变有效数据个数void resize(size_t n, const T& val = T()){if (n < size()){_finish = _start + n;}else{reserve(n);while (_finish != _start + n){*_finish = val;_finish++;}}}//扩容void reserve(size_t n){if (n > capacity()){size_t oldsize = size();T* tmp = new T[n];/*memcpy(tmp, _start, sizeof(T) * size());*/for (size_t i = 0; i < oldsize; i++){tmp[i] = _start[i];}delete[] _start;_start = tmp;_finish = oldsize + _start;_end_of_storage = n + _start;}}//尾插void push_back(const T& x){if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : 2 * capacity());}*_finish = x;_finish++;}//尾删void pop_back(){assert(_finish > _start);_finish--;}//重载下标操作符[]T& operator[](size_t i){return _start[i];}//赋值操作符---第一种写法//vector<T>& operator=(const vector<T>& v)//{//	if (this != &v)//	{//		delete[] _start;//		_start = _finish = _end_of_storage = nullptr;//		reserve(v.size());//		for (auto& e : v)//		{//			//this->push_back(e);//			push_back(e);//		}//	}//	return *this;//}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=(const vector<T>& v){swap(v);return *this;}//任意位置插入,insert插入数据后迭代器失效void insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);//满了扩容if (_finish == _end_of_storage){size_t len = pos - _start;reserve(capacity() == 0 ? 4 : 2 * capacity());pos = _start + len;}//挪动数据iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}//插入数据*pos = x;++_finish;}//erase删除数据iterator erase(iterator pos){assert(pos >= _start);assert(pos < _finish);iterator begin = pos + 1;while (begin < _finish){*(begin - 1) = *begin;++begin;}--_finish;return pos;}//析构~vector(){delete[] _start;_start = _finish = _end_of_storage = nullptr;}
private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;
};

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

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

相关文章

【AIGC学习笔记】扣子平台——精选有趣应用,探索无限可能

背景介绍&#xff1a; 由于近期业务发展的需求&#xff0c;我开始接触并深入了解了扣子平台的相关知识&#xff0c;并且通过官方教程自学了简易PE工作流搭建的技巧。恰逢周会需要准备与工作相关的分享主题&#xff0c;而我作为一个扣子平台的初学者&#xff0c;也想探索一下这…

mysql 学习6 DML语句,对数据库中的表进行 增 删 改 操作

添加数据 我们对 testdatabase 数据中 的 qqemp 这张表进行 增加数据&#xff0c;在这张表 下 打开 命令行 query console 在 软件中就是打开命令行的意思 可以先执行 desc qqemp; 查看一下当前表的结构。 插入一条数据 到qqemp 表&#xff0c;插入时要每个字段都有值 insert…

Java Web-Request与Response

在 Java Web 开发中&#xff0c;Request 和 Response 是两个非常重要的对象&#xff0c;用于在客户端和服务器之间进行请求和响应的处理&#xff0c;以下是详细介绍&#xff1a; Request&#xff08;请求对象&#xff09; Request继承体系 在 Java Web 开发中&#xff0c;通…

李沐vscode配置+github管理+FFmpeg视频搬运+百度API添加翻译字幕

终端输入nvidia-smi查看cuda版本 我的是12.5&#xff0c;在网上没有找到12.5的torch&#xff0c;就安装12.1的。torch&#xff0c;torchvision&#xff0c;torchaudio版本以及python版本要对应 参考&#xff1a;https://blog.csdn.net/FengHanI/article/details/135116114 创…

论文阅读(十六):利用线性链条件随机场模型检测阵列比较基因组杂交数据的拷贝数变异

1.论文链接&#xff1a;Detection of Copy Number Variations from Array Comparative Genomic Hybridization Data Using Linear-chain Conditional Random Field Models 摘要&#xff1a; 拷贝数变异&#xff08;CNV&#xff09;约占人类基因组的12%。除了CNVs在癌症发展中的…

ElasticSearch-文档元数据乐观并发控制

文章目录 什么是文档&#xff1f;文档元数据文档的部分更新Update 乐观并发控制 最近日常工作开发过程中使用到了 ES&#xff0c;最近在检索资料的时候翻阅到了 ES 的官方文档&#xff0c;里面对 ES 的基础与案例进行了通俗易懂的解释&#xff0c;读下来也有不少收获&#xff0…

实验二 数据库的附加/分离、导入/导出与备份/还原

实验二 数据库的附加/分离、导入/导出与备份/还原 一、实验目的 1、理解备份的基本概念&#xff0c;掌握各种备份数据库的方法。 2、掌握如何从备份中还原数据库。 3、掌握数据库中各种数据的导入/导出。 4、掌握数据库的附加与分离&#xff0c;理解数据库的附加与分离的作用。…

技术中台与终搜——2

文章目录 5、语言处理与自动补全技术探测5.1 自定义语料库5.1.1 语料库映射OpenAPI5.1.2 语料库文档OpenAPI 5.2 产品搜索与自动补全5.2.1 汉字补全OpenAPI5.2.2 拼音补全OpenAPI 5.3 产品搜索与语言处理5.3.1 什么是语言处理&#xff08;拼写纠错&#xff09;5.3.2 语言处理Op…

15_业务系统基类

创建脚本 SystemRoot.cs 因为 业务系统基类的子类 会涉及资源加载服务层ResSvc.cs 和 音乐播放服务层AudioSvc.cs 所以在业务系统基类 提取引用资源加载服务层ResSvc.cs 和 音乐播放服务层AudioSvc.cs 并调用单例初始化 using UnityEngine; // 功能 : 业务系统基类 public c…

【Linux】华为服务器使用U盘安装统信操作系统

目录 一、准备工作 1.1 下载UOS官方系统 &#xff11;.&#xff12;制作启动U盘 1.3 服务器智能管理系统iBMC 二、iBMC设置U盘启动 一、准备工作 1.1 下载UOS官方系统 服务器CPU的架构是x86-64还是aarch64&#xff09;,地址&#xff1a;统信UOS生态社区 - 打造操作系统创…

cursor重构谷粒商城04——vagrant技术快速部署虚拟机

前言&#xff1a;这个系列将使用最前沿的cursor作为辅助编程工具&#xff0c;来快速开发一些基础的编程项目。目的是为了在真实项目中&#xff0c;帮助初级程序员快速进阶&#xff0c;以最快的速度&#xff0c;效率&#xff0c;快速进阶到中高阶程序员。 本项目将基于谷粒商城…

如何在gitee/github上面搭建obsidian的图床

在搭建图床之前我们需要知道图床是一个什么东西,图床顾名思义就是存放图片的地方&#xff0c;那么我们为什么要搭建图床呢&#xff1f;因为我们在写博客的时候&#xff0c;很多同学都是在本地使用typora或者是obsidian进行markdown语法的文章的书写&#xff0c;文件格式通常都是…

SSM东理咨询交流论坛

&#x1f345;点赞收藏关注 → 添加文档最下方联系方式咨询本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345; 项目视频 js…

http的请求体各项解析

一、前言 做Java开发的人员都知道&#xff0c;其实我们很多时候不单单在写Java程序。做的各种各样的系统&#xff0c;不管是PC的 还是移动端的&#xff0c;还是为别的系统提供接口。其实都离不开http协议或者https 这些东西。Java作为编程语言&#xff0c;再做业务开发时&#…

【云安全】云原生-Docker(五)容器逃逸之漏洞利用

漏洞利用逃逸 通过漏洞利用实现逃逸&#xff0c;主要分为以下两种方式&#xff1a; 1、操作系统层面的内核漏洞 这是利用宿主机操作系统内核中的安全漏洞&#xff0c;直接突破容器的隔离机制&#xff0c;获得宿主机的权限。 攻击原理&#xff1a;容器本质上是通过 Linux 的…

微信小程序date picker的一些说明

微信小程序的picker是一个功能强大的组件&#xff0c;它可以是一个普通选择器&#xff0c;也可以是多项选择器&#xff0c;也可以是时间、日期、省市区选择器。 官方文档在这里 这里讲一下date picker的用法。 <view class"section"><view class"se…

[java] 面向对象进阶篇1--黑马程序员

目录 static 静态变量及其访问 实例变量及其访问 静态方法及其访问 实例方法及其访问 总结 继承 作用 定义格式 示例 总结 子类不能继承的内容 继承后的特点 成员变量 成员变量不重名 成员变量重名 super访问父类成员变量 成员方法 成员方法不重名 成员方法…

AI News(1/21/2025):OpenAI 安全疏忽:ChatGPT漏洞引发DDoS风险/OpenAI 代理工具即将发布

1、OpenAI 的安全疏忽&#xff1a;ChatGPT API 漏洞引发DDoS风险 德国安全研究员 Benjamin Flesch 发现了一个严重的安全漏洞&#xff1a;攻击者可以通过向 ChatGPT API 发送一个 HTTP 请求&#xff0c;利用 ChatGPT 的爬虫对目标网站发起 DDoS 攻击。该漏洞源于 OpenAI 在处理…

LLMs的星辰大海:大语言模型的前世今生

文章目录 一. LLM 的演进&#xff1a;从规则到智能的跃迁 &#x1f4ab;1.1 语言模型的蹒跚起步 &#x1f476;1.2 RNN 与 LSTM&#xff1a;序列建模的尝试 &#x1f9d0;1.3 Transformer 的横空出世&#xff1a;自注意力机制的革命 &#x1f4a5;1.4 LLM &#xff1a;从预测到…

7-Zip高危漏洞CVE-2025-0411:解析与修复

7-Zip高危漏洞CVE-2025-0411&#xff1a;解析与修复 免责声明 本系列工具仅供安全专业人员进行已授权环境使用&#xff0c;此工具所提供的功能只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利…