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

C++初阶-vector的模拟实现1

目录

1.序言

2.vector基本结构

3.size()和capacity()的模拟实现

4.begin()和end()函数的模拟实现

5.reserve函数的模拟实现1

6.push_back函数的模拟实现(含empty实现)

6.1解决问题

6.2最终代码(reverse的模拟实现2)

7.operator[]函数的模拟实现

8.pop_back函数的模拟实现

9.insert函数的模拟实现

10.erase函数的模拟实现

11.总结



1.序言

vector的模拟实现不会完全按照vector底层实现vector中的函数,但是会尽量接近,而在这个阶段我也会补充一下平常用得比较多的内容,而且前面的几个模拟实现不一定会是最终版本,所以可能实现的最终版本确定大部分是在vector模拟实现3或者2里面,这个阶段我还会进行举例来进行测试,通过测试得到代码的不足。也希望各位能把每个博客都看完,因为前面肯定是有些函数没有实现,没法测出代码的问题或者不足!

2.vector基本结构

在vector底层结构中我们知道了它的底层结构,所以这里就直接写了:

#include<iostream>
#include<vector>
#include<string>
using namespace std;
//防止命名冲突,用一个命名空间域进行分隔
namespace td
{template<class T>class vector{public:typedef T* iterator;//无参的构造函数的实现vector():_start(nullptr),_finish(nullptr),_end_of_storage(nullptr){ }//析构函数的实现~vector(){delete[] _start;_start = _finish = _end_of_storage = nullptr;}private:iterator _start;iterator _finish;iterator _end_of_storage;};//为了减少展开命名空间的麻烦,我们直接在命名空间内定义一个测试函数void test(){ }
}
int main()
{//用来测试td::test();return 0;
}

其中_start就是我们之前用来存储数据的数组,由于它是指针,所以可以用来表示首元素的地址。这就是一些简单的函数实现与以后我们测试的函数。

3.size()和capacity()的模拟实现

这个函数在之前的底层结构中返回值是size_type类型,实际上就是size_t类型,所以我们就不要这么麻烦了,也不要像之前的那种实现方式(通过begin()和end()函数以及一些额外的处理得到结果)了,直接返回_finish-_start和_end_of_storage-_start因为我们的我们vector是线性的,不用处理很多情况:

//size()函数的实现
size_t size() const
{return _finish - _start;
}
//capacity()函数的实现
size_t capacity() const
{return _end_of_storage - _start;
}

这个函数就不进行测试了,比较简单。

4.begin()和end()函数的模拟实现

这两个函数很简单,直接返回_start和_finish即可:

//普通的begin()函数的实现
iterator begin() 
{return _start;
}
//普通的end()函数的实现
iterator end() 
{return _finish;
}
typedef const T* const_iterator;
//const版本的begin的实现
const_iterator begin() const
{return _start;
}
//const版本的end的实现
const_iterator end() const
{return _finish;
}

5.reserve函数的模拟实现1

注:这个函数不是最终版本。

我们通过之前的string的reserve函数的实现知道了,我们应该先创建一个对象,然后再把数据拷贝过去,最后释放旧空间,然后把原变量赋值为新的即可:

//reserve函数的实现1
void reserve(size_t n)
{if (n > capacity()){//开辟新空间T* tmp = new T[n];//拷贝数据memcpy(tmp, _start, sizeof(T) * size());//释放空间delete[] _start;_start = tmp;_finish = _start + size();_end_of_storage = _start + n;}
}

6.push_back函数的模拟实现(含empty实现)

这个函数实现比较简单,首先判断空间是否满,我们可以先实现empty(判空),我们通过手动判断,如果满了则需要扩容,扩容后再进行插入,这里实现还是比较简单的!

//empty函数的实现
bool empty() const
{return begin() == end();
}
//push_back的实现
void push_back(const T& x)
{if (_finish == _end_of_storage){//先扩容//如果没有空间,就初始化为4//否则二倍扩容reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;++_finish;
}

用以下函数测试一下:

void test()
{vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);
}

则结果为:

为什么会有问题,我们调试一下。

6.1解决问题

我们调试一下:

为什么走完了finish还是0呢,我们可以大胆猜测:size()函数可能有问题!

我们通过size()函数的定义有:

//size()函数的实现
size_t size() const
{return _finish - _start;
}

如果代入表达式,那么最终得到结果:_finish=_finish这就是为什么没有解决的原因,难道把这个size()函数改一下?

不是这样的,我们可以通过发现:如果改变只能改变成其他形式如:end()-begin()那么好像最终还是一样的结果,所以不行。

这里的主要原因是开始_finish指向nullptr,_start指向了tmp,而导致了_finish为空,所以是:_start更新了,而_finish没有更新,故要_finish先更新才行。

所以可以改变一下:

6.2最终代码(reverse的模拟实现2)

注:这个不是最终版本的reverse的实现

//reserve函数的实现2
void reserve(size_t n)
{if (n > capacity()){//开辟新空间T* tmp = new T[n];//拷贝数据memcpy(tmp, _start, sizeof(T) * size());//释放空间delete[] _start;_finish = tmp + size();_start = tmp;_end_of_storage = _start + n;}
}

7.operator[]函数的模拟实现

这个函数实现比较简单,只要返回i位置的值即可:

//普通operator[]的实现
T& operator[](size_t i)
{//需包含头文件:assert.hassert(i < size());return _start[i];
}
//const的operator[]的实现
const T& operator[](size_t i) const
{assert(i < size());return _start[i];
}

8.pop_back函数的模拟实现

这个函数很简单,只要先判断是否为空后再--即可。代码如下:

//pop_back函数的实现
void pop_back()
{assert(_finish > _start);--_finish;
}

9.insert函数的模拟实现

注:这个不是最终版本

首先我们就需要判断空间是否满了,满了则需要扩容,然后每一个数据移动至后一位,然后最后插入该数据,最后再++_finish即可(这里涉及到一个很大的问题,我现在讲解不了,测试这个函数是在一定有问题的!):

//insert函数的实现
void insert(iterator pos, const T& x)
{//判断是否合法assert(pos >= _start);assert(pos <= _finish);//判满if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : capacity() * 2);}iterator it = _finish - 1;//移动数据while (it >= pos){*(it + 1) = *it;--it;}*pos = x;++_finish;
}

10.erase函数的模拟实现

这个函数比较简单,只要先判断该位置是否合法,然后再把该位置后面的数据往前移动一个位置即可。那么代码如下:

//erase函数的模拟实现
void erase(iterator pos)
{assert(pos >= _start);assert(pos <= _finish);if (pos == _finish){pop_back();return;}iterator it = pos + 1;while (it < _finish){*(it - 1) = *it;++it;}--_finish;
}

11.总结

该讲实现了一些比较简单的函数,不过有个函数是非常重要的:insert函数,那个函数测试时是有问题的,这涉及到了迭代器失效的问题,所以我不能很清楚的讲解这个原因,所以下讲将进行讲解:insert的最终实现与迭代器失效。这个迭代器失效我们会在很多地方遇到,所以特意分为一个章节来讲解的。好了,这讲就到这里,喜欢的可以一键三连哦!下讲再见!

http://www.xdnf.cn/news/7688.html

相关文章:

  • 利用 SQL Server 作业实现异步任务处理:一种简化系统架构的实践方案
  • 自然语言处理
  • 基于R语言地理加权回归、主成份分析、判别分析等空间异质性数据分析技术
  • 足式机器人经典控制常用的ROS库介绍
  • 如何使用AI辅助开发R语言
  • 星闪开发之buttondemo烧录后无效果思路
  • 基于双通道频谱分析的振动信号故障诊断2
  • vite ts vue中增加路由
  • 【HarmonyOS 5】金融应用开发鸿蒙组件实践
  • 基于PyTorch的医学影像辅助诊断系统开发教程
  • unity XCharts插件生成曲线图在UICanvas中
  • python训练 60天挑战-day31
  • 查看mysql配置文件my.cnf的位置
  • Docker-Harbor 私有镜像仓库使用指南
  • MyBatis 动态 SQL 标签详解教程:_set_、_trim_、_sql_、_choose_、_when_
  • 抢占短剧商业蓝海!AI 驱动 CPS 系统开发定制赋能高效变现
  • 数据结构*排序
  • tigase源码学习笔记-事件总线EventBus
  • 跨境外贸电商供应链一体化ERP管理系统
  • 波次拉料在精益生产中下的应用
  • OpenHarmony 5.0设置应用设置手势导航开关打开后重新关闭导航栏和设置界面重合
  • onlyoffice 源码 调试说明 -ARM和x86双模式安装支持
  • [Harmony]获取设备参数
  • SpringBoot 商城系统高并发引起的库存超卖库存问题 乐观锁 悲观锁 抢购 商品秒杀 高并发
  • 机械安全标准示例说明
  • 机器学习算法-聚类K-Means
  • 园区无人机智能巡检项目方案
  • 机器学习自然语言处理
  • SAP ECC即将停止支持,CIO如何应对S/4HANA的迁移挑战?
  • 【机器学习】logistic回归