[C++随笔录] vector模拟实现

vector模拟实现

  • 基本结构
  • 天选之子
    • 构造
    • 拷贝构造
    • 析构
    • operator=
  • 空间
    • reserve
    • resize
    • size && capacity
    • insert
    • push_back
    • erase
    • pop_back
  • 查 && 改
    • swap
    • operator[]
  • 源码

基本结构

// 可以是不同类型, 用类模板
template <class T>
class vector
{
public:// 源码里面成员变量的类型用的是迭代器,// 所以, 先定义迭代器类型typedef T* iterator;typedef const T* const_iterator;private:iterator _start = nullptr; // 相当于string类中的 _striterator _finish = nullptr; // 相当于string类中的 _sizeiterator _endofstorage = nullptr; // 相当于string类中的 _capacity
}
  1. 成员变量先给缺省值, 便于后面的构造函数 和 拷贝构造函数
  2. 迭代器是 T* , 跟string类中 迭代器是 char* 是一样的道理

天选之子

构造

  1. 默认构造函数
vector():_start(nullptr), _finish(nullptr), _endofstorage(nullptr)
{}

由于我们给成员变量都给了缺省值, 那么👇👇👇

vector()
{
}
  1. 开空间 + 初始化
    开空间 + 初始化 也是 resize 干的事情, 那么我们就可以直接复用
vector(int n, const T& val = T()) // 缺省值给T的默认构造出来的对象
{resize(n, val);
}
  1. 迭代器区间初始化

从上一篇文章得出: 同类型, 不同类型, 数组的区间都可以进行初始化. 迭代器多样化 ⇒ 套用模版
⇒ 进而我们得出: 在模版中可以套用模版

template <class InputIterator>
vector(InputIterator first, InputIterator last)
{int n = last - first;resize(n);int i = 0;while (first != last){_start[i++] = *first;first++;}}

拷贝构造

vector(const vector<T>& tem)
{// 找一块新空间 -- 外部深拷贝_start = new T[tem.capacity()];// memcpy(_start, tem._start, tem.capacity); -- 内部浅拷贝, 是错误的for (int i = 0; i < tem.size(); i++) // 内部深拷贝{_start[i] = tem[i];}// 更新size 和 capacity_finish = _start + tem.size();_endofstorage = _start + tem.capacity();}
  • 不能使用memcpy来进行拷贝数据的原因 && 外部和内部的深拷贝图示

析构

~vector()
{// 释放空间delete[] _start;// 置空_start = _finish = _endofstorage = nullptr;
}

operator=

// 现代写法 -- 传值传参, 巧借拷贝构造
T& operator=(const T tem)
{swap(tem);return *this;
}

空间

reserve

void reserve(size_t n)
{assert(n > 0);if (n > capacity()){size_t sz = size();  // 应该先保存一份sz <== _start会发生变化T* tem = new T[n];// 拷贝数据// memcpy(tem._start, _start, n); // 内部浅拷贝for (int i = 0; i < size(); i++){tem[i] = _start[i]; //调用了T的赋值, 从而实现深拷贝}// 更新_startdelete[] _start;_start = tem;// 更新size 和 capacity_finish = _start + sz;_endofstorage = _start + n;}}

resize

void resize(size_t n, const T& val = T())
{assert(n > 0);// 缩if (size() > n){_finish = _start + n;}// 扩else{reserve(n); // 先开n个空间// 从_finish位置开始初始化for (int i = size(); i < size() + n; i++){_start[i] = val;}// 改变_finish_finish = _finish + n;}
}

size && capacity

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

insert

void insert(iterator pos, const T& val = T())
{assert(pos >= _start && pos <= _finish);size_t len = pos - _start; // 在扩容前, 先保存一下pos的相对位置, 以免异地扩容, _start发生变化, 导致pos迭代器失效// 是否扩容if (_finish == _endofstorage){// 考虑到首次插入size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);pos = _start + len; // 扩容后, 更新pos}// 往后挪动数据iterator end = _finish - 1; while (end >= pos){*(end + 1) = *end;end--;}// 插入*pos = val;_finish = _finish + 1;}

push_back

void push_back(const T& val = T())
{ 是否扩容//if (_finish == _endofstorage)//{//	size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;//	reserve(newcapacity);//}//*_finish = val;//++_finish;// 复用insertinsert(_finish, val);
}

erase

iterator erase(iterator pos)
{assert(pos >= _start && pos < _finish);// 往前挪动数据iterator it = pos + 1 ;while (it != _finish){*(it - 1) = *it;it++;}// 更新size--_finish;return pos;
}

pop_back

void pop_back()
{// 复用erase, 传参_finish - 1erase(--end());}

查 && 改

swap

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

operator[]


T& operator[](size_t n)
{return _start[n];
}const T& operator[](size_t n)const 
{return _start[n];
}

源码

#pragma once#include<assert.h>
#include<iostream>namespace muyu
{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(){}vector(int n, const T& val = T()) // 缺省值给	T的默认构造出来的对象{resize(n, val);}template <class InputIterator>vector(InputIterator first, InputIterator last){int n = last - first;resize(n);int i = 0;while (first != last){_start[i++] = *first;first++;}}vector(const vector<T>& tem){// 找一块新空间 -- 外部深拷贝_start = new T[tem.capacity()];// memcpy(_start, tem._start, tem.capacity); -- 内部浅拷贝, 是错误的for (int i = 0; i < tem.size(); i++) // 内部深拷贝{_start[i] = tem[i];}// 更新size 和 capacity_finish = _start + tem.size();_endofstorage = _start + tem.capacity();}~vector(){// 释放空间delete[] _start;// 置空_start = _finish = _endofstorage = nullptr;}const size_t size()const{return _finish - _start;}const size_t capacity()const{return _endofstorage - _start;}void reserve(size_t n){assert(n > 0);if (n > capacity()){size_t sz = size();  // 应该先保存一份sz <== _start会发生变化T* tem = new T[n];// 拷贝数据// memcpy(tem._start, _start, n); // 内部浅拷贝for (int i = 0; i < size(); i++){tem[i] = _start[i]; //调用了T的赋值, 从而实现深拷贝}// 更新_startdelete[] _start;_start = tem;// 更新size 和 capacity_finish = _start + sz;_endofstorage = _start + n;}}void resize(size_t n, const T& val = T()){assert(n > 0);if (size() > n){_finish = _start + n;}else{reserve(n); // 先开n个空间// 从_finish位置开始初始化for (int i = size(); i < size() + n; i++){_start[i] = val;}// 改变_finish_finish = _finish + n;}}void push_back(const T& val = T()){ 是否扩容//if (_finish == _endofstorage)//{//	size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;//	reserve(newcapacity);//}//*_finish = val;//++_finish;insert(_finish, val);}void insert(iterator pos, const T& val = T()){assert(pos >= _start && pos <= _finish);size_t len = pos - _start; // 在扩容前, 先保存一下pos的相对位置, 以免异地扩容, _start发生变化, 导致pos迭代器失效// 是否扩容if (_finish == _endofstorage){size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);pos = _start + len; // 扩容后, 更新pos}// 往后挪动数据iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;end--;}// 插入*pos = val;_finish = _finish + 1;}T& operator[](size_t n){return _start[n];}const T& operator[](size_t n)const {return _start[n];}void swap(vector<T>& tem){std::swap(_start, tem._start);std::swap(_finish, tem._finish);std::swap(_endofstorage, tem._endofstorage);}iterator erase(iterator pos){assert(pos >= _start && pos < _finish);iterator it = pos + 1 ;while (it != _finish){*(it - 1) = *it;it++;}--_finish;return pos;}void pop_back(){// 复用erase, 传参_finish - 1erase(--end());}// 现代写法 -- 传值传参, 巧借拷贝构造T& operator=(const T tem){swap(tem);return *this;}private:iterator _start = nullptr; // 相当于string类中的 _striterator _finish = nullptr; // 相当于string类中的 _sizeiterator _endofstorage = nullptr; // 相当于string类中的 _capacity};
}

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

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

相关文章

画一个时钟(html+css+js)

这是一个很简约的时钟。。。。。。。 效果&#xff1a; 代码&#xff1a; <template><div class"demo-box"><div class"clock"><ul class"mark"><liv-for"(rotate, index) in rotatedAngles":key"i…

VBA技术资料MF59:从二维变体数组中删除一行数据

【分享成果&#xff0c;随喜正能量】小小的善业&#xff0c;能赢来大的利益&#xff0c;小小的恶业&#xff0c;同样也能招致严重的后果。这正如古语所云&#xff1a;“莫以善小而不为&#xff0c;莫以恶小而为之。。 我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效…

想学嵌入式开发,薪资怎么样?

想学嵌入式开发&#xff0c;薪资怎么样&#xff1f; 对于嵌入式工程师来说呢&#xff0c;它重点学习内容就是首先一定要打好基础&#xff0c;如果从编程语言角度来讲&#xff0c;那么可以在语言上选C或者C&#xff0c;你可以选择其中任何一门语言作为你的入门。 最近很多小伙伴…

Unity之NetCode多人网络游戏联机对战教程(1)

文章目录 1.什么是NetCode2.安装NGO 1.什么是NetCode 官网链接&#xff1a;https://docs-multiplayer.unity3d.com/netcode/current/about/ Netcode for GameObjects&#xff08;NGO&#xff09;是专为Unity构建的高级网络库。它能够在网络会话中将GameObject和世界数据同时发…

计算机组成原理——基础入门总结(二)

上一期的路径&#xff1a;基础入门总结&#xff08;一&#xff09; 目录 一.输入输出系统和IO控制方式 二.存储系统的基本概念 三.cache的基本概念和原理 四.CPU的功能和基本结构 五.总线概述 一.输入输出系统和IO控制方式 IO设备又可以被统一称为外部设备~ IO接口&…

每日一题~修剪二叉树

原题链接&#xff1a;669. 修剪二叉搜索树 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 思路分析&#xff1a; 由题可知&#xff0c;我们要将原来的二叉搜索树调整为值在 low~high 之间的新二叉搜索树&#xff0c;接下来我们分析一下针对不同的节点的处理方…

Hbase工作原理

Hbase&#xff1a;HBase 底层原理详解&#xff08;深度好文&#xff0c;建议收藏&#xff09; - 腾讯云开发者社区-腾讯云 Hbase架构图 同一个列族如果有多个store&#xff0c;那么这些store在不同的region Hbase写流程&#xff08;读比写慢&#xff09; MemStore Flush Hbas…

微信朋友圈的高级玩法

面对好友的生日&#xff0c;你还在傻傻的守点发朋友圈&#xff0c;节日庆祝你还在傻傻的守点官宣吗&#xff1f;还有你关注的那个他&#xff08;她&#xff09;&#xff0c;他&#xff08;她&#xff09;发的朋友圈你想成为第一个点赞评论的人吗&#xff1f;想和他进行更多的交…

如何自动获取短信验证码?

点击下方关注我&#xff0c;然后右上角点击...“设为星标”&#xff0c;就能第一时间收到更新推送啦~~~ 这篇文章通过解决实际项目开发中遇到的如何自动获取短信验证码的问题&#xff0c;进一步讲述在Java中如何使用正则。 Java中如何使用正则 Java中正则相关类位于java.util.r…

python pytesseract 中文文字批量识别

用pytesseract 来批量把图片转成文字 1、安装好 pytesseract 包 2、下载安装OCR https://download.csdn.net/download/m0_37622302/88348824https://download.csdn.net/download/m0_37622302/88348824 Index of /tesseracthttps://digi.bib.uni-mannheim.de/tesseract/ 我是…

DevOps与CI/CD常见面试问题汇总

01 您能告诉我们DevOps和Agile(敏捷)之间的根本区别吗&#xff1f; 答&#xff1a;尽管DevOps与敏捷方法&#xff08;这是最流行的SDLC[Software Development Life Cycle]方法之一&#xff09;有一些相似之处&#xff0c;但两者在软件开发方面都是根本不同的方法。以下是两者之…

SpringCloud Gateway--网关服务基本介绍和基本原理

&#x1f600;前言 本篇博文是关于SpringCloud Gateway的基本介绍&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满意是我的动力…

【lesson8】操作系统的理解和类比

文章目录 操作系统是什么&#xff1f;为什么要有操作系统&#xff1f;怎么做&#xff1f;学校的例子&#xff08;理解管理&#xff09;银行的例子&#xff08;类比操作系统&#xff09; 操作系统是什么&#xff1f; 操作系统是一款软件&#xff0c;是为了进行软硬件资源管理的…

400电话怎么办理(申请开通)

申请开通400电话是一项相对简单的过程&#xff0c;只需按照以下步骤进行操作即可。 第一步&#xff0c;选择400电话服务提供商。在市场上有很多公司提供400电话服务&#xff0c;您可以根据自己的需求和预算选择适合的服务商。可以通过搜索引擎、咨询朋友或者查看相关论坛等方式…

Python经典练习题(三)

文章目录 &#x1f340;第一题&#x1f340;第二题&#x1f340;第三题 &#x1f340;第一题 输入一行字符&#xff0c;分别统计出其中英文字母、空格、数字和其它字符的个数。 本题需要我们掌握的知识点在于&#xff0c;判断字符串&#xff0c;是数字还是字母还是啥的&#…

PROFINET主站转ETHERCAT协议网关

产品介绍 JM-PNM-ECT 是基于西门子1200PLC的一款 PROFINET 主站功能的通讯网关。该产品主要功能是将ETHERCAT 总线和 PROFINET 网络连接起来。 本网关连接到 PROFINET 总线中做为主站使用&#xff0c;连接到 ETHERCAT 总线中做为从站使用。 产品参数 技术参数 u 网关做为 P…

P1827 [USACO3.4] 美国血统 American Heritage(前序 + 中序 生成后序)

P1827 [USACO3.4] 美国血统 American Heritage&#xff08;前序 中序 生成后序&#xff09; 一、前言 二叉树入门题。涉及到树的基本知识、树的结构、树的生成。 本文从会从结构&#xff0c;到完成到&#xff0c;优化。 二、基础知识 Ⅰ、二叉树的遍历 前序遍历&#xff…

IDEA开发工具技巧

1.1 IDEA相关插件 idea插件下载地址&#xff1a;https://plugins.jetbrains.com/ 开发必装插件&#xff1a; &#xff08;1&#xff09; 快速查找api接口 RestfulTool 插件&#xff0c;推荐指数⭐⭐⭐⭐⭐ [RestfulTool搜索插件使用详解](https://blog.csdn.net/weixin_450147…

vue3硅谷甄选01 | 使用vite创建vue3项目及项目的配置 环境准备 ESLint配置 prettier配置 husky配置 项目集成

文章目录 使用vite创建vue3项目及项目的配置1.环境准备2.项目配置ESLint校验代码工具配置 - js代码检测工具1.安装ESLint到开发环境 devDependencies2.生成配置文件:.eslint.cjs**3.安装vue3环境代码校验插件**4. 修改.eslintrc.cjs配置文件5.生成ESLint忽略文件6.在package.js…

工作应当有挑战

有挑战 才能有所成长 正所谓人到山前必有路 是挑战 一般就会有未知 未知往往伴随着困难 有困难 并不可怕&#xff0c;也不必自我抱怨&#xff0c;自我抱怨只会陷入无尽的精神内耗 我们只要做好自己 困难就会迎刃而解 如果自己的获得 没有达到自己的期望 其实那也不必气馁 再…