[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.mzph.cn/news/85337.shtml

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

相关文章

将来已来-SoftwareDemo软件测试种子的埋下去-第二次重大情绪点的触及到

岗位需要&#xff0c;一头扎进了软件测试的方向里面去了。过去下过无数次决心&#xff0c;做成一个事情的方向&#xff0c;想不到换成了软件测试的了。不知道这次&#xff0c;会不会持续下去。 这是进入软件开发行业以来的一种重大变革&#xff0c;犹如泽火革卦象&#xff1b; …

git和github的入门操作

之前因为工作中用的都是SVN版本控制工具&#xff0c;没接触过git和github&#xff0c;现在开始深入自学Django框架技术后&#xff0c;看到官网推荐使用git&#xff0c;然后这两天网上查阅了很多文章教程&#xff0c;学到入门操作需要学习的点&#xff0c;太多的知识点要后面慢慢…

PHP常见的SQL防注入方法

利用Mysqli和PDO 产生原因主要就是一些数据没有经过严格的验证&#xff0c;然后直接拼接 SQL 去查询。导致产生漏洞&#xff0c;比如&#xff1a; $id $_GET[id]; $sql "SELECT name FROM users WHERE id $id";因为没有对 $_GET[‘id’] 做数据类型验证&#xf…

感知器算法

感知器是一种简单的机器学习算法&#xff0c;用于二元分类问题&#xff08;即将数据分为两个类别&#xff09;。它是人工神经网络的早期形式&#xff0c;由Frank Rosenblatt在1957年提出。感知器的主要思想是通过学习权重来分隔不同类别的数据点。 以下是感知器算法的基本步骤&…

Mac配置iTerm样式终端

一、MacOs系统 MacOs中终端使用iTerm2 1. 配置oh-my-zsh oh my zsh 的地址&#xff1a; https//github.com/ohmyzsh/ohmyzsh 插件存放位置&#xff1a;~/.oh-my-zsh/plugins 下载常用的插件 git clone http://github.com/zsh-users/zsh-syntax-highlighting.git 修改配…

英伟达 nvidia 官方code llama在线使用

新一代编程语言模型Code Llama面世&#xff1a;重新定义编程的未来 随着人工智能和机器学习技术的迅速发展&#xff0c;我们现在迎来了一款革命性的大型编程语言模型——Code Llama。该模型是基于Llama 2研发的&#xff0c;为开放模型中的佼佼者&#xff0c;其性能达到了行业领…

React组件化开发

1.组件的定义方式 函数组件Functional Component类组件Class Component 2.类组件 export class Profile extends Component {render() {console.log(this.context);return (<div>Profile</div>)} } 组件的名称是大写字符开头&#xff08;无论类组件还是函数组件…

ISTQB术语表

此术语表为国际软件测试认证委员会&#xff08;ISTQB&#xff09;发布的标准术语表。此表历经数次修改、完善&#xff0c;集纳了计算机行业界、商业界及政府相关机构的见解及意见&#xff0c;在国际化的层面上达到了罕有的统一性及一致性。参与编制此表的国际团体包括澳大利亚、…

MyBatisPlus(四)表映射:@TableName

表映射 数据库中的表名&#xff0c;和项目中的实体类名&#xff0c;并不相同&#xff0c;则需要通过注解TableName来进行映射。 未映射前报错示例 数据库表名&#xff1a;tb_user 实体类名&#xff1a;User 测试代码 Autowiredprivate UserMapper userMapper;Testvoid selec…

CUDA和cuDNN的安装

参考资料&#xff1a;https://zhuanlan.zhihu.com/p/83971195 目录 CUDA和cuDNN介绍安装验证 CUDA和cuDNN介绍 CUDA(ComputeUnified Device Architecture)&#xff0c;是显卡厂商NVIDIA推出的运算平台。 CUDA是一种由NVIDIA推出的通用并行计算架构&#xff0c;该架构使GPU能够…

Mrtrix3--将mif文件转换为nifit文件--以及批处理代码

#如果您想在mrview中看到fd.mif,则可以使用fixel2voxel fd.mif mean fd_mean.miffixel2voxel fd.mif mean fd_mean.mif mrconvert fd_mean.mif fd_mean.nii.gz #convert to nifit----fixel_in_template_space_NOT_REORIENTED/fd_mean#fixel2voxel fd.mif mean fd…

网络初识

一 IP 地址 概念: IP 地址主要用于表示网络主机、其他网络设备&#xff08;如路由器&#xff09;的网络地址。简单说&#xff0c;IP地址用于定位主机的网络地址 格式 IP 地址是一个32为的二进制数&#xff0c;通常被分割为4个“8位二进制数“&#xff08;也就是4个字节&…

排序算法(一)

排序算法(一&#xff09; 冒泡排序选择排序插入排序希尔排序堆排序 冒泡排序 冒泡排序是一种十分稳定的排序&#xff0c;其思想是通过两两比较&#xff0c;改变位置&#xff0c;从而每次让一个数出现在其该出现的位置该排序由于很稳定&#xff0c;所以不论数据是否有序&#xf…

什么是语法糖?Java中有哪些语法糖?

什么是语法糖&#xff1f;Java中有哪些语法糖&#xff1f; 语法糖 语法糖&#xff08;Syntactic Sugar&#xff09;&#xff0c;也称糖衣语法&#xff0c;是由英国计算机学家 Peter.J.Landin 发明的一个术语&#xff0c;指在计算机语言中添加的某种语法&#xff0c;这种语法对…

小米笔试题——01背包问题变种

这段代码的主要思路是使用动态规划来构建一个二维数组 dp&#xff0c;其中 dp[i][j] 表示前 i 个产品是否可以组合出金额 j。通过遍历产品列表和可能的目标金额&#xff0c;不断更新 dp 数组中的值&#xff0c;最终返回 dp[N][M] 来判断是否可以组合出目标金额 M。如果 dp[N][M…

C++提高编程:01 模板

这里写目录标题 1 模板的概念2 函数模板2.1 函数模板语法2.2 函数模板注意事项2.3 函数模板案例2.4 普通函数与函数模板的区别2.5 普通函数与函数模板的调用规则2.6 模板的局限性 3 类模板3.1 类模板语法3.2 类模板与函数模板区别3.3 类模板中成员函数创建时机3.4 类模板对象做…

thinkphp8路由

thinkphp8已出来有好一段时间了。这些天闲来无事&#xff0c;研究了下tp8的路由。默认情况下&#xff0c;tp8的路由是在route\app.php的文件里。但在实际工作中&#xff0c;我们并不会这样子去写路由。因为这样不好管理。更多的&#xff0c;是通过应用级别去管理路由。假如项目…

2023华为杯研究生数学建模C题分析

完整的分析查看文末名片获取&#xff01; 问题一 在每个评审阶段&#xff0c;作品通常都是随机分发的&#xff0c;每份作品需要多位评委独立评审。为了增加不同评审专家所给成绩之间的可比性&#xff0c;不同专家评审的作品集合之间应有一些交集。但有的交集大了&#xff0c;则…

conda的安装和使用

参考资料&#xff1a; https://www.bilibili.com/read/cv8956636/?spm_id_from333.999.0.0 https://www.bilibili.com/video/BV1Mv411x775/?spm_id_from333.999.0.0&vd_source98d31d5c9db8c0021988f2c2c25a9620 目录 conda是啥以及作用conda的安装conda的启动conda的配置…

操作符 | MATLAB

文章目录 算术运算模除法和舍入关系运算符逻辑运算集合运算按位运算 算术运算 操作符含义操作符含义操作符含义sum元素数组求和cumsum累计和movsum移动总和diff差分和近似导数.*乘法*矩阵乘法prod数组元素的乘积cumprod累积乘积pagemtimes按页矩阵乘法tensorprodTensor produc…