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

vector的简单模拟实现_C++

目录

一、vector的数据结构

二、vector的构造

三、vector的增删查改及空间管理

四、全部代码


一、vector的数据结构

vector以线性连续空间为基础来定义数据结构以及扩展功能。vector的两个迭代器,分别是start和finish,分别指向配置得来的已被使用的空间。还有一个迭代器,end_of_storage指向整块连续空间的尾端。 

iterator _start = nullptr;
iterator _finish = nullptr;
iterator _endofstorage = nullptr;

(此处迭代器变量名前加‘_'表示我们不是真正的vector而是模拟出来的) 

这些迭代器应该被private所修饰,那么,可以设计如下构造函数来提取vector的首尾,这样既保护了迭代器,又便于提取首位:

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

vector的实际配置大小要比需求量大一些,以便将来可以扩充。也就是说,vector的容量大小永远大于或者等于其大小。一旦其容量等于其大小,即是满载,当有新的元素加入时,vector就要进行扩容。

示意图如下: 

二、vector的构造

vector的构造如下:

(constructor)构造函数声明接口说明
vector();无参构造
vector(size_type n, const value_type& val = value_type());构造并初始化n个val
vector (const vector& x);拷贝构造
vector (InputIterator first, InputIterator last);使用迭代器进行初始化构造

我们来一一实现。

无参构造:

vector()
{}

初始化n个构造:

vector(size_t n, const T& val = T())
{resize(n, val);
}vector(int n, const T& val = T())
{resize(n, val);
}

拷贝构造:

vector(const vector<T>& v)
{_start = new T[v.capacity()];//memcpy(_start, v._start, sizeof(T)*v.size());for (size_t i = 0; i < v.size(); i++){_start[i] = v._start[i];}_finish = _start + v.size();_endofstorage = _start + v.capacity();
}

使用迭代器初始化构造:

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

除此之外,也可以重载=来实现构造,原理同拷贝构造:

vector<T>& operator=(vector<T> v)
{swap(v);return *this;
}

最后,既然有构造函数,那必然有析构函数呀:

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

三、vector的增删查改及空间管理

vector的增删查改功能函数如下:

vector增删查改接口说明
push_back尾插
pop_back尾删
find查找。(注意这个是算法模块实现,不是vector的成员接口)
insert在position之前插入val
erase删除position位置的数据
swap交换两个vector的数据空间
operator[]像数组一样访问

要实现push_back,我们先实现insert:

iterator insert(iterator pos, const T& x)
{assert(pos >= _start && pos <= _finish);if (_finish == _endofstorage){size_t len = pos - _start;size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);pos = _start + len;}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;return pos;
}

这样,在设计push_back时,直接调用insert函数就好:

void push_back(const T& x)
{insert(end(), x);
}

要实现pop_back,不妨参考push_back的实现过程,先实现erase:

iterator erase(iterator pos)
{assert(pos >= _start && pos < _finish);iterator it = pos + 1;while (it != _finish){*(it - 1) = *it;++it;}--_finish;return pos;
}

再直接调用erase即可实现pop_back:

void pop_back()
{erase(--end());
}

要交换两个vector的数据空间的话,把关键迭代器交换即可:

void swap(vector<T>& v)
{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);
}

operator[]的实现如下:

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

vector的空间管理功能如下:

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize改变vector的size
reserve改变vector的capacity

前三个都很简单,返回相应的值即可:

size_t size() const
{return _finish - _start;
}size_t capacity() const
{return _endofstorage - _start;
}bool empyt() const
{return ((_endofstorage - _start) == 0 ? true : false);
}

重点实现的是resize和reserve:

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;}}
}

reserve如下:

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;}
}

四、全部代码

全部代码如下:

#include<assert.h>namespace bit
{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(size_t n, const T& val = T()){resize(n, val);}vector(int n, const T& val = T()){resize(n, val);}template<class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}}vector(){}vector(const vector<T>& v){_start = new T[v.capacity()];for (size_t i = 0; i < v.size(); i++){_start[i] = v._start[i];}_finish = _start + v.size();_endofstorage = _start + v.capacity();}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);}vector<T>& operator=(vector<T> v){swap(v);return *this;}~vector(){if (_start){delete[] _start;_start = _finish = _endofstorage = nullptr;}}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& val = T()){if (n < size()){_finish = _start + n;}else{reserve(n);while (_finish != _start + n){*_finish = val;++_finish;}}}void push_back(const T& x){insert(end(), x);}void pop_back(){erase(--end());}size_t capacity() const{return _endofstorage - _start;}size_t size() const{return _finish - _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];}iterator insert(iterator pos, const T& x){assert(pos >= _start && pos <= _finish);if (_finish == _endofstorage){size_t len = pos - _start;size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);// 解决pos迭代器失效问题pos = _start + len;}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;return pos;}iterator erase(iterator pos){assert(pos >= _start && pos < _finish);iterator it = pos + 1;while (it != _finish){*(it - 1) = *it;++it;}--_finish;return pos;}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _endofstorage = nullptr;};
}

相关文章:

vector的简单模拟实现_C++

目录 一、vector的数据结构 二、vector的构造 三、vector的增删查改及空间管理 四、全部代码 一、vector的数据结构 vector以线性连续空间为基础来定义数据结构以及扩展功能。vector的两个迭代器&#xff0c;分别是start和finish&#xff0c;分别指向配置得来的已被使用的空…...

合并两个有序链表,剑指offer,力扣

目录 力扣题目地址&#xff1a; 原题题目&#xff1a; 我们直接看题解吧&#xff1a; 解题方法&#xff1a; 审题目事例提示&#xff1a; 解题思路&#xff1a; 具体流程如下&#xff1a; 代码实现&#xff1a; 知识补充&#xff1a; 力扣题目地址&#xff1a; 21. 合并两个有序…...

Delphi 12 Athens 发布了!

官方安装包 ☞ https://altd.embarcadero.com/download/radstudio/12.0/RADStudio_12_0_4915718.iso 安装辅助工具、控件可以戳这里 &#xff1a;Delphi 12 资源 RAD Stuido 12 Athens &#xff0c;这次更新的细节还是比较多的&#xff0c;但主要还是多端&#xff08;iOS、An…...

基于Haclon的Blob分析

任务要求&#xff1a; 请用BLOB分析的方法计算图中所有灰度值在120和255之间的像素构成的8连通区域的面积与中心点坐标。 Blob基础&#xff1a; 分析过程&#xff1a;首先获取图像&#xff0c;然后根据特征对原始图像进行阈值分割&#xff08;区分背景像素和前景像素&#xf…...

安卓手机好用的清单软件有哪些?

生活中每个人都有丢三落四的习惯&#xff0c;伴随着生活节奏的加快&#xff0c;人们常忘事的情况会更加频繁的出现&#xff0c;这时候很多人就开始选择手机上记录清单类的软件&#xff0c;安卓手机在手机市场中占有很大的分量&#xff0c;在安卓手机上好用的记录清单的软件有哪…...

【追求卓越02】数据结构--链表

引导 今天我们进入链表的学习&#xff0c;我相信大家对链表都很熟悉。链表和数组一样&#xff0c;作为最基础的数据结构。在我们的工作中常常会使用到。但是我们真的了解到数组和链表的区别吗&#xff1f;什么时候使用数组&#xff0c;什么时候使用链表&#xff0c;能够正确的选…...

qt按照不同编码格式读取文字(UTF-16LE,UTF-8,UTF-8BOM,UTF-16BE)

enum class EncodingFormat : int {ANSI 0,//GBKUTF16LE,UTF16BE,UTF8,UTF8BOM, }; EncodingFormat VideoPlayer::FileCharacterEncoding(const QString &fileName) {//假定默认编码utf8EncodingFormat code EncodingFormat::UTF8;QFile file(fileName);if (file.open(QI…...

R语言和RStudio的下载安装(非常简便舒适)

目录 R语言和RStudio的关系R语言和Tableau下载R语言进入官网选择清华镜像源Download R for Windows选择base版本开始下载进行安装配置环境变量检查是否安装成功 下载RStudio进入官网点击下载进行安装检查是否安装成功打开选择R语言环境成功打开显示四个工作区 R语言和RStudio的…...

SQL注入漏洞发现和利用,以及SQL注入的防护

一、背景 SQL注入漏洞是一种常见的软件安全问题&#xff0c;它发生在应用程序的数据库层中。其核心原理是将用户输入的数据当做代码来执行&#xff0c;违反了“数据与代码分离”的原则。具体来说&#xff0c;攻击者通过构造恶意的SQL查询语句&#xff0c;使得应用程序在执行SQ…...

Jmeter 分布式压测

为什么要分布式 jmeter是100%纯java开发的程序&#xff0c;虚拟用户是以线程实现的&#xff0c;在大量并发情况下&#xff0c;很容易出现CPU、内存消耗过大的问题&#xff0c;甚至会出现java内存溢出。一般一台电脑设置500-600线程数即可&#xff0c;如果超过1000线程&#xf…...

Docker 安装 Apache

目录 拉取官方 Apache 镜像 查看本地镜像 列出正在运行的容器 运行 Apache 容器 创建一个 HTML 文件&#xff1a;index.html 访问 Apache 拉取官方 Apache 镜像 查找 Docker Hub 上的 httpd 镜像。 可以通过 Tags 查看其他版本的 httpd&#xff0c;默认是最新版本 httpd…...

python变量、常量、数据类型

一、变量 变量是存储在内存中的值&#xff0c;这就意味着在创建变量时会在内存中开辟一个空间。 基于变量的数据类型&#xff0c;解释器会分配指定内存&#xff0c;并决定什么数据可以被存储在内存中。 因此&#xff0c;变量可以指定不同的数据类型&#xff0c;这些变量可以…...

注册中心CAP架构剖析

Nacos 支持 AP 或 CP AP Nacos 通过临时节点实现 AP 架构&#xff0c;将服务列表放在内存中&#xff1b; CP Nacos 通过持久化节点实现 CP 架构&#xff0c;将服务列表放在文件中&#xff0c;并同步到内存&#xff0c;通过 Raft 协议算法实现&#xff1b; 通过配置 epheme…...

SVN创建分支

一 从本地创建方式可指定版本号进行分支创建。 1、在本地目录右击 -----> 点击branch/tag(分支/标签) From: 源&#xff0c;可指定具体的版本号&#xff0c; To path: 可通过"..."选择分支路径 最后点击确定&#xff0c;交由服务器执行创建。 二 通过SVN客…...

Vue 设置v-html中元素样式

使用方式&#xff1a; <<< img { max-width: 100% } 如&#xff1a;要将v-html中的图片元素(img)的最大宽度设置为100%. <template><div ><div class"rtfDiv book" v-html"content"></div></div> </template&…...

连接服务器的脚本

对于记不住的服务器密码且不愿用三方工具俺简单写了个脚本&#xff08;检测下最近shell脚本的学习效果咋样&#xff09; expect 是处理交互的一种脚本语言&#xff0c;spawn启动指定进程 -> expect获取指定关键字 -> send想指定进程发送指定指令 -> 执行完成后退出 sp…...

ChatGPT/GPT4丨编程助手;AI画图;数据分析;科研/项目实现;提示词工程技巧;论文写作等

ChatGPT 在论文写作与编程方面也具备强大的能力。无论是进行代码生成、错误调试还是解决编程难题&#xff0c;ChatGPT都能为您提供实用且高质量的建议和指导&#xff0c;提高编程效率和准确性。此外&#xff0c;ChatGPT是一位出色的合作伙伴&#xff0c;可以为您提供论文写作的…...

35的程序员被辞了可以自己接外包啊?为什么都那么悲观呢?

35的年纪&#xff0c;上有老下有小&#xff0c;即将步入中年危机&#xff0c;在这个节骨眼上被辞&#xff0c;能不悲观吗&#xff1f; 在这个年纪人们往往追求的是稳定的工作和生活&#xff0c;而进入一个自己不熟悉的行业并不是一个好的选择。 况且&#xff0c;你认为的外包…...

2020年09月 Scratch(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 执行下面程序,屏幕上最多会看到多少个苹果? A:10个 B:11个 C:1个 D:无法确定 答案:B 第2题 关于下面程序,说法正确的是 ? A:执行 后,马上执行...

SpringBoot面试之SpringBoot自动装配原理

SpringBoot自动装配原理 背景 最近因为各种原因&#xff0c;我又重新加入到了找工作的大军当中。昨天在面试的时候与面试官聊到我们项目都是基于SpringBoot开发的&#xff0c;然后面试官就顺口问了句&#xff1a;”SpringBoot项目会引入许多的starter&#xff0c;比如&#x…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...