[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.xdnf.cn/news/139190.html

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

相关文章

【DLL修复工具下载】一键修复电脑丢失d3dcompiler_47.dll问题方法

在我们使用电脑的过程中&#xff0c;有时候会遇到一些错误提示&#xff0c;其中“缺失 d3dcompiler_47.dll”就是比较常见的一种。那么&#xff0c;d3dcompiler_47.dll 到底是什么呢&#xff1f;为什么会出现缺失的情况&#xff1f;丢失 d3dcompiler_47.dll 又会对电脑产生什么…

远程控制桌面软件是否支持远程防护墙配置

远程控制桌面软件是一种便捷的工具&#xff0c;它能够帮助用户在远程访问和操作计算机桌面。然而&#xff0c;远程控制软件是否支持远程防火墙配置这个问题的答案并不是简单的是或否。下面将从软件设计的角度和实际使用情况的角度来解释这个问题。 首先&#xff0c;让我们了解一…

SQL server 创建存储过程

SQL Server如何创建存储过程 存储过程&#xff1a; 可以理解为完成特定功能的一组 SQL 语句集&#xff0c;存储在数据库中&#xff0c;经过第一次编译&#xff0c;之后的运行不需要再次编译&#xff0c;用户通过指定存储过程的名字并给出参数&#xff08;如果该存储过程带有参数…

小节9:Python之numpy

numpy全称为Numerical Python&#xff0c;是很多数据或科学相关Python包的基础。 1、numpy数组&#xff08;ND array N维数组&#xff09; numpy数组是更适合数据分析的列表。 numpy的数组和Python的内置列表有相似之处&#xff0c;也有不同之处。 相似之处&#xff1a;我们…

K8s的网络——Underlay和Overlay网络

0. 基础知识 1&#xff09;网络7层基础知识 在网络7层协议基础里&#xff0c; 第一层物理链路&#xff1b;第二层是数据链路层&#xff0c;在第一层的基础上引入MAC地址做数据转发。MAC地址在局域网内具有唯一性&#xff0c;主机A发送数据时&#xff0c;会向局域网内进行广播…

【LeetCode-简单题】589. N 叉树的前序遍历

文章目录 题目方法一&#xff1a;单循环栈做法方法二&#xff1a;递归 题目 方法一&#xff1a;单循环栈做法 关键在于子节点的入栈顺序&#xff0c;决定了子节点的出栈顺序&#xff0c; 因为是前序遍历 所以压栈顺序先让右边的入栈 依次往左 这样左边的节点会在栈顶 这样下次…

小白的入门二叉树(C语言实现)

前言&#xff1a; 二叉树属于数据结构的一个重要组成部分&#xff0c;很多小白可能被其复杂的外表所吓退&#xff0c;但我要告诉你的是“世上无难事&#xff0c;只怕有心人”&#xff0c;我将认真的对待这篇博客&#xff0c;我相信只要大家敢于思考&#xff0c;肯定会有所收获…

成都瀚网科技:抖音提供差异化​​亮点!

在抖音平台上&#xff0c;精选联盟是一个专门为优质品牌提供展示和推广机会的合作项目。对于斗店主来说&#xff0c;如何成功对接精选联盟并实现上市是一个重要目标。在这篇文章中&#xff0c;我们将分享一些豆点与精选联盟对接的方法&#xff0c;并提供上币指南。 1、提升店铺…

2023 蓝帽杯初赛web部分取证复现

前言&#xff1a;初赛进线下了&#xff0c;计划着在决赛前突击学习一下取证&#xff0c;但时间还是太紧 只看了很多内存取证和手机取证 计算机取证和服务器取证没掌握 ---( 不过复赛没考&#xff0c;也算狗运了) 目录 <1> web-LovePHP(file()函数侧信道攻击) <2&g…

基于微信小程序的美术馆预约平台设计与实现(源码+lw+部署文档+讲解等)

前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb;…

【LeetCode热题100】--53.最大子数组和

53.最大子数组和 使用动态规划&#xff1a; 状态定义&#xff1a;设动态规划列表dp&#xff0c;dp[i]代表以元素nums[i]为结尾的连续子数组最大和 转移方程&#xff1a;若dp[i-1]≤0,说明dp[i-1]对dp[i]产生负贡献&#xff0c;即dp[i-1]nums[i]还不如nums[i]本身大 初始状态&…

Redis GEO 类型与 API 结合,地理位置优化的绝佳实践

&#x1f52d; 嗨&#xff0c;您好 &#x1f44b; 我是 vnjohn&#xff0c;在互联网企业担任 Java 开发&#xff0c;CSDN 优质创作者 &#x1f4d6; 推荐专栏&#xff1a;Spring、MySQL、Nacos、Java&#xff0c;后续其他专栏会持续优化更新迭代 &#x1f332;文章所在专栏&…

基于PHP语言研发的抖音矩阵系统源代码开发部署技术文档分享

一、概述 本技术文档旨在介绍抖音SEO矩阵系统源代码的开发部署流程&#xff0c;以便开发者能够高效地开发、测试和部署基于PHP语言的开源系统。通过本文档的指引&#xff0c;您将能够掌握抖音SEO矩阵系统的开发环境和部署方案&#xff0c;从而快速地构建出稳定、可靠的短视频S…

网络爬虫-----爬虫的分类及原理

目录 爬虫的分类 1.通用网络爬虫&#xff1a;搜索引擎的爬虫 2.聚焦网络爬虫&#xff1a;针对特定网页的爬虫 3.增量式网络爬虫 4.深层网络爬虫 通用爬虫与聚焦爬虫的原理 通用爬虫&#xff1a; 聚焦爬虫&#xff1a; 爬虫的分类 网络爬虫按照系统结构和实现技术&#…

竞赛选题 基于深度学习的植物识别算法 - cnn opencv python

文章目录 0 前言1 课题背景2 具体实现3 数据收集和处理3 MobileNetV2网络4 损失函数softmax 交叉熵4.1 softmax函数4.2 交叉熵损失函数 5 优化器SGD6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习的植物识别算法 ** …

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…

PIL或Pillow学习2

接着学习下Pillow常用方法&#xff1a; PIL_test1.py : 9, Pillow图像降噪处理由于成像设备、传输媒介等因素的影响&#xff0c;图像总会或多或少的存在一些不必要的干扰信息&#xff0c;我们将这些干扰信息统称为“噪声”&#xff0c; 比如数字图像中常见的“椒盐噪声”&…

Postman使用_接口导入导出

文章目录 Postman导入数据Collections导出数据Environments导出数据Postman导出所有数据 Postman导入数据 可以导入collections&#xff08;接口集&#xff09;、Environments&#xff08;环境配置&#xff09;通过分享的链接或导出的JSON文件导入数据&#xff08;还可以从第三…

Pixea Plus for Mac:极简图片浏览,高效图片管理

在处理和浏览图片时&#xff0c;我们往往需要一个得心应手的工具&#xff0c;尤其是当你的图片库包含了各种不同格式&#xff0c;例如JPEG、HEIC、psd、RAW、WEBP、PNG、GIF等等。今天&#xff0c;我们要推荐的&#xff0c;就是一款极简、高效的Mac图片浏览和管理工具——Pixea…

Crazy Excel:Excel中的泥石流

Crazy Excel又名&#xff1a;疯狂Excel。是一款PC端的Excel软件工具&#xff0c;该软件支持windows, mac os等主流操作系统。 正如其名&#xff0c;作者在设计之初就加入了一些疯狂的设计&#xff0c;目的是创作出更加好用有效的excel工具。 不管是专业还是小白&#xff0c;…