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

STL之vector

目录

  • vector模拟实现
    • 一. vector的基本框架
    • 二. 常用方法及实现
      • 1.初始化和清理
        • a. 默认构造函数
        • b. 析构函数
      • 2. 迭代器
        • a. begin
        • b. end
      • 3.数据访问
        • a. size
        • b. capacity
        • c. operator[]
        • d. front
        • c. back
      • 4.增删查改操作
        • a. reserve
        • b. resize
        • c. insert
        • d. push_back
        • e. erase
        • f. pop_back
      • 5.构造函数
        • a.迭代器区间构造
        • b. swap
        • c. 拷贝构造
        • d. operator=
        • c.n个val的构造
    • 三.小结
      • 1.代码结构
      • 2.迭代器失效
        • a.插入时
        • b.删除时
      • 3.迭代器操作

vector模拟实现

一. vector的基本框架

template<typename T>
class vector
{
public:typedef T* iterator;private:iterator _start;iterator _finish;iterator _end_of_storage;
}

使用库中的string类需要包含头文件#inlcude<vector>,并且使用std::命名空间
在这里插入图片描述

_start:指向起始元素的地址; _finish:指向最后一个元素的下一个地址; _end_of_storage:指向所申请空间结尾的下一个位置地址

其底层是将数据顺序存储的,即使用一段连续的空间。

二. 常用方法及实现

实现的顺序来依次进行介绍

1.初始化和清理

a. 默认构造函数

vector():_start(nullptr),_finish(nullptr),_end_of_storage(nullptr)
{}

b. 析构函数

~vector()
{delete[] _start;_start = _finish = _end_of_storage = nullptr;
}

2. 迭代器

vector是顺序存储的结构,因此可以用T*(原生指针)当做其迭代器

typedef T* iterator;
typedef const T* const_iterator;

a. begin

iterator begin()
{return _start;
}
const_iterator begin() const
{return _start;
}

b. end

iterator end()
{return _finish;
}
const_iterator end() const
{return _finish;
}

3.数据访问

a. size

size_t size() const
{return _finish - _start;
}

b. capacity

size_t capacity() const
{return _end_of_storage - _start;
}

指针相减,得到的是其中该类型元素的个数

c. operator[]

const T& operator[](size_t pos) const
{assert(pos < size());return *(_start + pos);
}
T& operator[](size_t pos)
{assert(pos < size());return *(_start + pos);
}

d. front

T& front()
{assert(size() > 0);return *_start;
}
const T& front() const
{assert(size() > 0);return *_start;
}

c. back

const T& back() const
{assert(size() > 0);return *(_finish - 1);
}

4.增删查改操作

a. reserve

void reserve(size_t n)
{if (n > capacity()){T* temp = new T[n];//将原空间的数据拷贝到新空间中size_t sz = size();for (size_t i = 0; i < sz; ++i){temp[i] = *(_start + i);}delete[] _start;_start = temp;_finish = _start + sz;_end_of_storage = _start + n;}
}

申请n个元素的空间,如果n<原有空间,则不做操作

b. resize

void resize(size_t n, const T& val = T())
{if (n < size()){//保留前n个元素_finish = _start + n;}else{//申请n个元素空间reserve(n);//新增的元素赋valiterator cur = _finish;_finish = _start + n; while (cur != _finish){*cur = val;++cur;} }
}

调整元素个数为n个,如果n<size,只保留前n个元素;如果n>size,新增的元素为val。

其中如果没有传val参数,则使用缺省值T():T类型的匿名对象(内置类型,如:int() = 0)

c. insert

iterator insert(iterator pos, const T& val)
{assert(pos >= _start);assert(pos <= _finish);//如果空间满了就扩容if (_finish == _end_of_storage){//扩容后,可能使用新的空间,pos指向改变size_t s = pos - _start;reserve(capacity() == 0 ? 4 : 2 * capacity());pos = _start + s;}//将pos位到最后元素都向后移动1位iterator cur = _finish - 1;while (cur >= pos){*(cur+1) = *cur;--cur;}*pos = val;++_finish;return pos;
}

扩容操作可能使用新空间,所以要更新迭代器

d. push_back

void push_back(const T& val)
{insert(_finish, val);
}

尾插,在最后一个元素的下一个位置(_finish)存放val

e. erase

iterator erase(iterator pos)
{assert(pos >= _start);assert(pos < _finish);//将pos后的元素都向前移动1位iterator cur = pos + 1;while (cur < _finish){*(cur - 1) = *cur;++cur;}--_finish;return pos;
}

删除pos指向的元素,并返回删除位置的下一个位置的迭代器

f. pop_back

void pop_back()
{erase(_finish - 1);
}

删除最后一个元素

5.构造函数

a.迭代器区间构造

template<class InputIterator>
vector(InputIterator first, InputIterator last):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{while (first != last){push_back(*first);++first;}
}

通过传入的迭代器区间,来根据其区间的值来创建vector对象

b. 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对象的内容,通过作用域限定符::来调用库函数中的swap函数,完成对内置类型的成员变量的交换。

c. 拷贝构造

传统写法:

vector(const vector<T>& v):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{//提前申请空,减少扩容reserve(v.size());for (const auto& e : v){push_back(e);}
}

现代写法:

通过一个局部对象,和swap来完成

vector(const vector<T>& v):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{//调用迭代器区间来构造temp对象vector<T> temp(v.cbegin(),v.cend());swap(temp);
}

通过初始化列表,对成员变量进行初始化,然后和经迭代器区间构造函数得到的temp对象进行交换内容,完成拷贝构造。该函数调用结束,局部对象temp会自动调用析构函数,并销毁。

d. operator=

//赋值运算符重载,非构造函数
vector<T>& operator= (vector<T> v)
{swap(v);return *this;
}

传参时,会调用拷贝构造函数完成对局部对象v的初始化,然后交换*this和v的内容,完成对自身对象的赋值。

c.n个val的构造

vector(size_t n, const T& val = T()):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{reserve(n);for (size_t i = 0; i < n; ++i){push_back(val);}
}/*定义时,n应该是非负数的,所以使用size_t,但传参时,通常传入的数字是int类型的,
例如:vector<int> v(5,0);(构造含5个0的v对象),此时参数类型是:(int,int)
无法做到和上面(size,int)的精准匹配,编译器会选择根据
//template<class InputIterator>
//vector(InputIterator first, InputIterator last)
生成调用(int,int)的区间构造构造函数,从而发生错误
所以加入下面的函数
*/
vector(int n, const T& val = T()):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{reserve(n);for (int i = 0; i < n; ++i){push_back(val);}
}

构造的vector对象含n个val元素。其中如果没有传val参数,则使用缺省值T():T类型的匿名对象(内置类型,如:int() = 0)

三.小结

1.代码结构

vector代码代码,可以放在自己的命名空间中,避免冲突

#include <iostream>
#include <assert.h>namespace yyjs
{   template<typename T>class vector{public:typedef T* iterator;typedef const T* const_iterator;...};}

上述的成员函数都是放在class vector类体中,并public修饰

2.迭代器失效

a.插入时

扩容操作可能使用新空间,所以要更新迭代器,如果只是进行扩容,迭代器pos所指向的可能就是野指针,因此会产生迭代器失效因此的程序崩溃

在这里插入图片描述

b.删除时

在这里插入图片描述

在删除vi对象中一个奇数后,迭代器依旧指向被删除元素的位置,然后++,向下一个位置移动

由于erase()操作需要将元素向前挪动,所以之前的迭代器实际上是失效的,因此导致 5 5 5被错过

在这里插入图片描述

3.迭代器操作

由于vector是顺序存储的,所以直接使用其元素指针做其迭代器:typedef T* iterator;

因此,对于iterator的操作,如*(解引用)、++、>等,实际上使用的底层库函数已经实现的对指针(内置类型)的操作符

相关文章:

STL之vector

目录 vector模拟实现一. vector的基本框架二. 常用方法及实现1.初始化和清理a. 默认构造函数b. 析构函数 2. 迭代器a. beginb. end 3.数据访问a. sizeb. capacityc. operator[]d. frontc. back 4.增删查改操作a. reserveb. resizec. insertd. push_backe. erasef. pop_back 5.构…...

2020年CSP-J认证 CCF非专业级别软件能力认证第一轮真题-单项选择题解析

2020 CCF认证第一轮&#xff08;CSP-J&#xff09;真题 一、单项选择题 (共15题&#xff0c;每2分&#xff0c;共30分;每题有且有一个正确选项&#xff09; 1、在内存储器中每个存储单元都被赋予一个唯一的序号,称为 A、下标 B、序号 C、地址 D、编号 答案&#xff1a;C…...

vscode Delete `␍⏎·····`

在公司拉取代码报错 Delete ␍⏎&#xff0c;首先问题的关键是换行导致&#xff0c;相信你看别的博客也知道为什么了&#xff0c;但是我使用别的博客的解决办法&#xff0c;没搞定&#xff0c;无论是配置 auto 还是命令行执行&#xff0c;都不行 下面介绍我的解决办法 我使用…...

读书笔记-《ON JAVA 中文版》-摘要16[第十六章 代码校验]

文章目录 第十六章 代码校验1. 测试1.1 单元测试1.2 JUnit1.3 测试覆盖率的幻觉 2. 前置条件2.1 断言&#xff08;Assertions&#xff09;2.2 Java 断言语法2.3 Guava 断言2.4 使用断言进行契约式设计2.4.1 检查指令2.4.2 前置条件2.4.3 后置条件2.4.4 不变性2.4.5 放松 DbC 检…...

SQL Server:打造高效数据管理系统的利器

使用SQL Server进行数据管理 简介 SQL Server是由Microsoft开发的一款关系型数据库管理系统&#xff0c;它可以用于存储和管理大量结构化数据。本篇博客将介绍如何使用SQL Server进行数据管理。 数据库连接 在开始使用SQL Server之前&#xff0c;需要先建立与数据库的连接。…...

代码随想录二刷day20 | 二叉树之 654.最大二叉树 617.合并二叉树 700.二叉搜索树中的搜索 98.验证二叉搜索树

day20 654.最大二叉树617.合并二叉树700.二叉搜索树中的搜索98.验证二叉搜索树 654.最大二叉树 题目链接 解题思路&#xff1a; 本题属于构造二叉树&#xff0c;需要使用前序遍历&#xff0c;因为先构造中间节点&#xff0c;然后递归构造左子树和右子树。 确定递归函数的参数…...

python基础知识(十三):numpy库的基本用法

目录 1. numpy的介绍2. numpy库产生矩阵2.1 numpy将列表转换成矩阵2.2 numpy创建矩阵 3. numpy的基础运算4. numpy的基础运算25. 索引 1. numpy的介绍 numpy库是numpy是python中基于数组对象的科学计算库。 2. numpy库产生矩阵 2.1 numpy将列表转换成矩阵 import numpy as …...

【SA8295P 源码分析】16 - TouchScreen Panel (TP)线程函数 tp_recv_thread() 源码分析

【【SA8295P 源码分析】16 - TouchScreen Panel (TP)线程函数 tp_recv_thread 源码分析 一、TP 线程函数:tp_recv_thread()二、处理&上报 坐标数据 cypress_read_touch_data()系列文章汇总见:《【SA8295P 源码分析】00 - 系列文章链接汇总》 本文链接:《【SA8295P 源码…...

Python3数据分析与挖掘建模(13)复合分析-因子关分析与小结

1.因子分析 1.1 探索性因子分析 探索性因子分析&#xff08;Exploratory Factor Analysis&#xff0c;EFA&#xff09;是一种统计方法&#xff0c;用于分析观测变量之间的潜在结构和关联性。它旨在确定多个观测变量是否可以归结为较少数量的潜在因子&#xff0c;从而帮助简化…...

【stable diffusion】图片批量自动打标签、标签批量修改(BLIP、wd14)用于训练SD或者LORA模型

参考&#xff1a; B站教学视频【&#xff1a;AI绘画】新手向&#xff01;Lora训练&#xff01;训练集准备、tag心得、批量编辑、正则化准备】官方教程&#xff1a;https://github.com/darkstorm2150/sd-scripts/blob/main/docs/train_README-en.md#automatic-captioning 一、…...

TCP可靠数据传输

TCP的可靠数据传输 1.TCP保证可靠数据传输的方法 TCP主要提供了检验和、序号/确认号、超时重传、最大报文段长度、流量控制等方法实现了可靠数据传输。 检验和 通过检验和的方式&#xff0c;接收端可以检测出来数据是否有差错和异常&#xff0c;假如有差错就会直接丢失该TC…...

Python 私有变量和私有方法介绍

Python 私有变量和私有方法介绍 关于 Python 私有变量和私有方法&#xff0c;通常情况下&#xff0c;开发者可以在方法或属性名称前加上单下划线&#xff08;_&#xff09;&#xff0c;以表示该方法或属性仅供内部使用&#xff0c;但这只是一种约定&#xff0c;并没有强制执行禁…...

Kotlin Lambda表达式和匿名函数的组合简直太强了

Kotlin Lambda表达式和匿名函数的组合简直太强了 简介 首先&#xff0c;在 Kotlin 中&#xff0c;函数是“第一公民”&#xff08;First Class Citizen&#xff09;。因此&#xff0c;它们可以被分配为变量的值&#xff0c;作为其他函数的参数传递或者函数的返回值。同样&…...

uniapp 小程序 获取手机号---通过前段获取

<template><!-- 获取手机号&#xff0c;登录内容 --><view><!-- 首先需要先登录获取code码&#xff0c;然后才可以获取用户唯一标识openid以及会话密钥及用于解密获取手机的加密信息 --><view click"login">登录</view><view…...

面板安全能力持续增强,新增日志审计功能,1Panel开源面板v1.3.0发布

2023年6月12日&#xff0c;现代化、开源的Linux服务器运维管理面板1Panel正式发布v1.3.0版本。 在这一版本中&#xff0c;1Panel进一步增强了安全方面的能力&#xff0c;包括新增SSH配置管理、域名绑定和IP授权支持&#xff0c;以及启用网站防盗链功能。此外&#xff0c;该版本…...

k8s学习-CKS考试必过宝典

目录 CKS考纲集群安装&#xff1a;10%集群强化&#xff1a;15%系统强化&#xff1a;15%微服务漏洞最小化&#xff1a;20%供应链安全&#xff1a;20%监控、日志记录和运行时安全&#xff1a;20% 报名模拟考试考试注意事项考前考中考后 参考 CKS考纲 集群安装&#xff1a;10% 使…...

jmeter如何将上一个请求的结果作为下一个请求的参数

目录 1、简介 2、用途 3、下载、简单应用 4、如何将上一个请求的结果作为下一个请求的参数 1、简介 在JMeter中&#xff0c;可以通过使用变量来将上一个请求的结果作为下一个请求的参数传递。 ApacheJMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测…...

JAVA如何学习爬虫呢?

学习Java爬虫需要掌握以下几个方面&#xff1a; Java基础知识&#xff1a;包括Java语法、面向对象编程、集合框架等。 网络编程&#xff1a;了解HTTP协议、Socket编程等。 HTML、CSS、JavaScript基础&#xff1a;了解网页的基本结构和样式&#xff0c;以及JavaScript的基本语…...

距离保护原理

距离保护是反映故障点至保护安装处的距离&#xff0c;并根据距离的远近确定动作时间的一种保护。故障点距保护安装处越近&#xff0c;保护的动作时间就越短&#xff0c;反之就越长&#xff0c;从而保证动作的选择性。测量故障点至保护安装处的距离&#xff0c;实际上就是用阻抗…...

从微观世界的RST包文视角助力企业网络应用故障排查和优化

1. 前言 随着互联网的普及和发展&#xff0c;各行业的业务和应用越来越依赖于网络。然而&#xff0c;网络环境的不稳定性和复杂性使得出现各种异常现象的概率变得更高了。这些异常现象会导致业务无法正常运行&#xff0c;给用户带来困扰&#xff0c;甚至影响企业的形象和利益。…...

企业微信开发,简单测试。

企业微信开发&#xff0c;参考文档&#xff1a; https://github.com/wechat-group/WxJava/wiki...

element日期选择设置默认时间el-date-picker

<el-date-pickerv-model"rangeDate"style"width:350px"type"daterange"value-format"yyyy-MM-dd"change"dataChange"start-placeholder"开始日期"end-placeholder"结束日期"></el-date-picker…...

AB32VG:SDK_AB53XX_V061(3)IO口复用功能的补充资料

文章目录 1.IO口功能复用表格2.功能映射寄存器 FUNCTION03.功能映射寄存器 FUNCTION14.功能映射寄存器 FUNCTION2 AB5301A的官方数据手册很不完善&#xff0c;没有开放出来。我通过阅读源码补充了一些关于IO口功能复用寄存器的资料。 官方寄存器文档&#xff1a;《 AB32VG1_Re…...

UnityVR--组件10--UGUI简单介绍

目录 前言 UI基础组件 1. Canvas 2. EventSystem 3. Image 4. Text/TextMeshPro/InputField 5. Button控件 其他 前言 UGUI是Unity推出的新的UI系统&#xff0c;它与Unity引擎结合得更紧密&#xff0c;并拥有强大的屏幕自适应和更简单的深度处理机制&#xff0c;更容易使用和…...

k8s 探针

1.前言 Kubernetes探针(Probe)是用于检查容器运行状况的一种机制。探针可以检查容器是否正在运行&#xff0c;容器是否能够正常响应请求&#xff0c;以及容器内部的应用程序是否正常运行等。在Kubernetes中&#xff0c;探针可以用于确定容器的健康状态&#xff0c;如果容器的健…...

【爬虫】4.4 Scrapy 爬取网站数据

目录 1. 建立 Web 网站 2. 编写 Scrapy 爬虫程序 为了说明 scrapy 爬虫爬取网站多个网页数据的过程&#xff0c;用 Flask 搭建一个小型的 Web 网站。 1. 建立 Web 网站 &#xff08;1&#xff09;books.html <!DOCTYPE html> <html lang"en"> <h…...

PureComponent和Component的区别和底层处理机制

PureComponent和Component都是React中的组件类&#xff0c;但它们在实现细节和使用上有些差别。 Component是React中定义组件的基类&#xff0c;它的shouldComponentUpdate方法默认返回true&#xff0c;也就是说&#xff0c;每次调用setState或forceUpdate方法都会引发组件重新…...

python3 爬虫相关学习9:BeautifulSoup 官方文档学习

目录 1 BeautifulSoup 官方文档 报错暂时保存 2 用bs 和 requests 打开 本地html的区别&#xff1a;代码里的一段html内容 2.1 代码和运行结果 2.2 用beautiful 打开 本地 html 文件 2.2.1 本地html文件 2.2.2 soup1BeautifulSoup(html1,"lxml") 2.3 用reque…...

物联网Lora模块从入门到精通(九)Flash的读取与存储--结题

一、前言 这将是"物联网Lora模块从入门到精通"系列的最后一篇文章&#xff0c;相信各位同僚通过前面八篇文章的分享已经极好的掌握了Lora模块的编程&#xff0c;本文的Flash的读取与存储将是Lora模块开发的最后一块&#xff0c;感谢大家的陪伴与支持&#xff01; 希望…...

STM32MP157_PRO开发板的第一个驱动程序

文章目录 目的&#xff1a;为什么编译驱动程序之前要先编译内核&#xff1f;编译内核编译设备树编译安装内核模块编译内核模块安装内核模块到 Ubuntu 的NFS目录下备用 安装内核和模块到开发板上编译 led 驱动在开发板安装驱动模块下载驱动程序安装驱动模块 目的&#xff1a; 在…...

山东滨州网站建设公司/大连网络营销seo

本文实例讲述了PHP yield关键字功能与用法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;yield 关键字是php5.5版本推出的一个特性。生成器函数的核心是yield关键字。它最简单的调用形式看起来像一个return申明&#xff0c;不同之处在于普通return会返回值并终止函数…...

品牌网站制作流程/百度一下你就知道移动官网

项目介绍 一款 PHP 语言基于 Laravel9.x、Layui、MySQL等框架精心打造的一款模块化、插件化、高性能的前后端分离架构敏捷开发框架&#xff0c;可用于快速搭建前后端分离后台管理系统&#xff0c;本着简化开发、提升开发效率的初衷&#xff0c;框架自研了一套个性化的组件&…...

wordpress用户勾选/平台seo什么意思

SRM&#xff1a;机房内部竞赛&#xff0c;哼唧。 描述 给一个 01 串设为其 S&#xff0c;询问是否存在只出现两次的 01 串 T。 这里的出现定义为存在一串下标 &#xff0c;满足 且 。 输入格式 一行&#xff0c;一个 01 串 输出格式 一行&#xff0c;字母 Y 表示存在&#xff…...

腾达建设哪里的/整站优化方案

rsync 学习 参考 http://www.cnblogs.com/itech/archive/2009/08/10/1542945.html 模式1 本地直接拷贝&#xff0c; 这个其实是调用了 cp 命令&#xff0c; 跟 rsync 服务器&#xff0c; 客户端无关。 /usr/myapp/logs 是本地日志目录 rsync /usr/myapp/logs /usr/myapp/logs2 …...

帮别人做网站哪里可以接单/网站推广软件免费版

闲来无事&#xff0c;看到了拓扑排序就学习了一下。 拓扑排序&#xff1a; 算导上说是使用深搜来对有向无环图进行排序&#xff0c;得到一种线性次序。不过深搜的理解还理解不到。估计是深搜学的不怎么样吧&#xff01; 说说我理解的这个线性次序吧。我认为算导上的例子就特别…...

图书管理系统网站开发/类似互推商盟的推广平台

1、get_shell Linux的nc命令&#xff0c;用于设置路由器 参数及作用&#xff1a; -g<网关> 设置路由器跃程通信网关&#xff0c;最多可设置8个。-G<指向器数目> 设置来源路由指向器&#xff0c;其数值为4的倍数。-h 在线帮助。-i<延迟秒数> 设置时间间隔&…...