【C++】STL-vector模拟实现

目录

1、vactor的模拟实现

1.1 成员变量

1.2 size、capacity

1.3 迭代器

1.4 构造、析构、拷贝构造、operator=

1.5 push_back、pop_back、reserve

1.6 operator[]

1.7 insert、erase

1.8 resize

2、使用memcpy拷贝问题


1、vactor的模拟实现

1.1 成员变量

vector是顺序表,但是并不像之前在数据结构中一样会有一个指针动态开辟出的空间的指针、size、capacity,而是由3个指针构成的

1.2 size、capacity

1.3 迭代器

1.4 构造、析构、拷贝构造、operator=

因为类对象会开辟空间,所以要自己实现深拷贝的拷贝构造和operatpr=

1.5 push_back、pop_back、reserve

此时这个reserve是有问题的

1.6 operator[]

1.7 insert、erase

此时也会有迭代器失效问题,因为如果需要增容,通过reserve增完后,_start、_finish、_endofstorage都指向了新的空间,而pos仍然指向原来的空间,所以需要更新pos的位置

1.8 resize

2、使用memcpy拷贝问题

在上面的reserve中使用了memcpy,在遇到自定义类型时会出错,因为memcpy是浅拷贝

问题分析:
1. memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中
2. 如果拷贝的是内置类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。
结论:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是浅拷贝,否则可能会引起内存泄漏甚至程序崩溃

上面的tmp[i]=_start[i]也不一定是string的operator=,应该是T的operator=,只是这里是string的

#include<iostream>
#include<cassert>
using namespace std;
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():_start(nullptr),_finish(nullptr),_endofstorage(nullptr){}~Vector(){delete[] _start;_start = _finish = _endofstorage = nullptr;}/*Vector(const Vector<T>& v){_start = new T[v.capacity()];_finish = _start;_endofstorage = _start + capacity();for (size_t i = 0; i < v.size(); i++){*_finish = v[i];_finish++;}}*//*Vector(const Vector<T>& v){_start = new T[v.capacity()];_finish = _start + v.size();_endofstorage = _start + v.capacity();memcpy(_start, v._start, sizeof(T) * v.size());}*/Vector(const Vector<T>& v):_start(nullptr), _finish(nullptr), _endofstorage(nullptr){reserva(v.capacity());//防止push_back频繁扩容for (const auto& e : v)push_back(e);}//Vector<T>& operator=(const Vector<T>& v)//{//	if (this != &v)//	{//		delete[] _start;//		_start = new T[v.capacity()];//		memcpy(_start, v._start, sizeof(T) * v.size());//		//也可以一个一个赋值//	}//	return *this;//}void swap(Vector<T>& v){::swap(_start, v._start);::swap(_finish, v._finish);::swap(_endofstorage, v._endofstorage);//这里是在局部调用全局的swap,所以前面加::}Vector<T>& operator=(Vector<T> v){swap(v);return *this;}//for (size_t i = 0; i < sz; i++)//{//	tmp[i] = _start[i];//利用string的operator=的深拷贝//}void reserve(size_t n){if (n > capacity()){size_t sz = size();//先记录_finish相对_start的偏移量T* tmp = new T[n];if (_start){注意这里一定要判断一下,当_start是空的时候使用memcoy会报错且因为_start是空,也没必要将上面的内容拷贝到tmp上memcpy(tmp, _start, sizeof(T) * size());delete[] _start;}_start = tmp;_finish = _start + sz;_endofstorage = _start + n;}}void push_back(const T& x)//用引用是因为T可能是自定义类型{if (_finish == _endofstorage)//满了则扩容{size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;reserve(newcapacity);}*_finish = x;++_finish;//insert(_finish, x);也可以直接复用insert}void pop_back(){assert(_start < _finish);//保证不为空_finish--;//erase(_finish-1);//也可复用erase}void insert(iterator pos, const T& x){assert(pos <= _finish);if (_finish == _endofstorage){size_t n = pos - _start;//计算pos相对_start的偏移量size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;reserve(newcapacity);pos = _start + n;//更新pos的位置}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;end--;}*pos = x;_finish++;}iterator erase(iterator pos){assert(pos < _finish);//确保删除位置有效iterator it = pos;while (it < _finish){*it = *(it + 1);it++;}_finish--;return pos;//删除后原本的下一个就到了pos的位置//所以返回迭代器就是返回原来的位置}void resize(size_t n, const T& val = T()){//上面给的缺省值不能给0,因为不一定是int类型,T()是针对任何类型的//int i = int();  ->  i=0;//int i = int(7)  ->  i=7;//C++为了让内置类型可以兼容模板if (n <= size())//如果比size还小或等于,不用填充,直接缩小{_finish = _start + n;}else//需要填充{if (n > capacity())//扩容{reserve(n);}//填充,从_finish的位置开始向后填充//填充时不能用memcpy将val直接弄到_finish到_start+n的位置//因为memcpy是浅拷贝,若是自定义类型且开辟了空间//会直接让所以的都指向同一块空间while (_finish < _start + n){*_finish = val;_finish++;}}}T& operator[](size_t i)//可读可写{assert(i < size());//断言,防止i越界return _start[i];}const T& operator[](size_t i) const//只可读{assert(i < size());//断言,防止i越界return _start[i];}size_t size() const{return _finish - _start;}size_t capacity() const{return _endofstorage - _start;}
private:iterator _start;//指向动态开辟数组的起始位置iterator _finish;//指向动态开辟数组的有值的下一个位置iterator _endofstorage;//指向动态开辟数组的末尾
};

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

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

相关文章

架构师系列-Nginx、OpenResty(一)- 基本使用配置

Nginx 模块 高度模块化的设计是 Nginx 的架构基础&#xff0c;Nginx 服务器被分解为多个模块&#xff0c;每个模块就是一个功能模块&#xff0c;只负责自身的功能&#xff0c;模块之间严格遵循“高内聚&#xff0c;低耦合”的原则。 核心模块 核心模块是 Nginx 服务器正常运行…

数据库系统原理实验报告4 | 数据完整性

整理自博主本科《数据库系统原理》专业课自己完成的实验报告&#xff0c;以便各位学习数据库系统概论的小伙伴们参考、学习。 专业课本&#xff1a; ———— 本次实验使用到的图形化工具&#xff1a;Heidisql 目录 一、实验目的 二、实验内容 1、建表 2、对1题中创建的Stud…

<计算机网络自顶向下> 无连接传输UDP

UDP&#xff1a;User Datagram Protocol “尽力而为”的服务 报文可能丢掉或者乱序好处&#xff1a; 效率高&#xff08;不建立连接无拥塞控制和流量控制【应用->传输的速率主机->网络的速率】&#xff09;报文段的头部很小&#xff08;开销小&#xff09;UDP被用于 流媒…

JVM常见的垃圾回收器

1、回收方法区&#xff1a; 方法区回收价值很低&#xff0c;主要回收废弃的常量和无用的类。 方法区中的存储&#xff1a; 方法区中存储的是加载的类的信息&#xff0c;常量&#xff0c;静态变量&#xff0c;即时编译后的代码等数据&#xff0c;所以回收的对象也就是这些内…

如何在一台服务器上同时运行搭载JDK 8, JDK 17, 和 JDK 21的项目:终极指南

&#x1f42f; 如何在一台服务器上同时运行搭载JDK 8, JDK 17, 和 JDK 21的项目&#xff1a;终极指南 &#x1f680; 摘要 在企业开发环境中&#xff0c;常常需要在同一台服务器上运行使用不同Java开发工具包&#xff08;JDK&#xff09;版本的多个项目。本文详细介绍如何在L…

报错import build constraints exclude all Go files in

好久没用fyne突然报错 报错import ...go-gl.. build constraints exclude all Go files in go-gl .. 检查gcc --version正常输出 检查gcc版本正常&#xff0c;路径正常。 尝试解决的方法&#xff0c; 1.重新安装依赖&#xff0c;不行 2.重新配置下载地址&#xff0c;不…

window平台C#实现软件升级功能(控制台)

window平台C#实现软件升级功能 之前用window窗体实现过一个升级功能&#xff0c;后来发现多个项目都需要升级功能&#xff0c;现改成可接收参数实现一种通用的exe.改用控制台方式实现这个升级功能&#xff0c;这样不仅实现了接收参数&#xff0c;升级程序体积也比原来的窗体形式…

河道采砂执法监管信息化平台:科技赋能,智慧监管

随着信息技术的飞速发展&#xff0c;信息化平台已经成为提升行业监管效率和水平的重要工具。河道采砂作为水利资源管理的重要环节&#xff0c;其执法监管同样需要与时俱进&#xff0c;利用先进技术手段提升监管效能。河道采砂执法监管信息化平台便是这一背景下的产物&#xff0…

从底层分析并详解SpringAOP底层实现

首先分析AOP的实现 首先切面&#xff08;Advisor&#xff09;由通知(Advice)和切点(Pointcut)组成 包括前置通知后置通知等等最终都会被转化为实现 MethodInterceptor 接口的环绕通知 先看一段代码了解一下是aop是怎么运作的 首先定义了两个类实现了MethodInterceptor接口&…

Unity HDRP Water Surface 水系统 基础教程

Unity HDRP Water Surface 水系统 基础教程 Unity Water SurfaceUnity 项目创建Unity Water Surface&#xff1a;Ocean&#xff08;海洋&#xff09;简介Ocean&#xff1a;Transform、GeneralOcean&#xff1a;Simulation&#xff08;仿真模拟&#xff09;Ocean&#xff1a;Sim…

C++之STL-String

目录 一、STL简介 1.1 什么是STL 1.2 STL的版本 1.3 STL的六大组件 ​编辑 1.4 STL的重要性 二、String类 2.1 Sting类的简介 2.2 string之构造函数 2.3 string类对象的容量操作 2.3.1 size() 2.3.2 length() 2.3.3 capacity() 2.3.4 empty() 2.3.5 clear() 2.3.6…

【IDEA】在IntelliJ IDEA中导入Eclipse项目:详细指南

IntelliJ IDEA和Eclipse是两款常用的集成开发环境&#xff08;IDE&#xff09;&#xff0c;在软件开发中经常会遇到需要在它们之间迁移项目的情况。本文将重点介绍如何在IntelliJ IDEA中导入Eclipse项目&#xff0c;以帮助开发者顺利地迁移他们的项目&#xff0c;并在IntelliJ …

echarts 堆叠柱状图 顶部添加合计

堆叠有3个&#xff0c;后面加了一个对象显示顶部的数据&#xff0c; 其实主要的代码还是在series 的第四项&#xff0c;需要注意的是 series的第四项中的data需要为 data: [0, 0, 0] 顶部的统计才能显示出来 增加的代码如下 {name: 综合,type: bar,stack: total,label: {sh…

【Java框架】SpringMVC(三)——异常处理,拦截器,文件上传,SSM整合

目录 异常处理解释局部异常处理全局异常 拦截器拦截器介绍作用:拦截器和过滤器之间的区别拦截器执行流程代码实现补充 文件上传依赖配置MultipartResolver编写文件上传表单页APIMultipartFileFile.separator必须对上传文件进行重命名代码示例 SpringMVC文件上传流程多文件上传 …

AWS制作WordPress在国内外的利弊?

AWS作为全球领先的云计算服务供应商&#xff0c;为WordPress提供了强大且灵活的托管环境&#xff0c;使用AWS来搭建和运行WordPress无疑是个不错的选择。即便如此使用AWS制作还是会有些许利弊&#xff0c;九河云作为AWS的合作伙伴来为读者们仔细探讨AWS在WordPress的利弊。 利&…

学python的第十九天

网络通信和访问数据库 1.1 基本的网络知识 TCP/IP IP是低级的路由协议&#xff0c;它将数据拆分在许多小的数据包中&#xff0c;并通过网络将他们发送到某一特定地址&#xff0c;但无法保证所有包都抵达目的地&#xff0c;也不能保证包按顺序抵达 TCP&#xff08;传输控制协议…

深度学习系列65:数字人openHeygen详解

1. 主流程分析 从inference.py函数进入&#xff0c;主要流程包括&#xff1a; 1&#xff09; 使用cv2获取视频中所有帧的列表&#xff0c;如下&#xff1a; 2&#xff09;定义Croper。核心代码为69行&#xff1a;full_frames_RGB, crop, quad croper.crop(full_frames_RGB)。…

Android MVVM架构 + Retrofit完成网络请求

关于Retrofit&#xff0c;这个应该不是一个很新颖的东西了&#xff0c;简单过一下吧 1.由Square公司开发&#xff0c;基于Type-safe的REST客户端。 2.使用注解来定义API接口&#xff0c;使得HTTP请求变得简洁且易于维护。 3.支持同步和异步请求&#xff0c;可与RxJava、Corouti…

【安卓13】解决带GMS编译报super分区空间不足错误

1、错误信息 2、解决方案 不同供应商修改分区大小的文件路径不一样&#xff0c;但是万变不离其宗&#xff0c;根据报错信息全局搜索关键词BOARD_SUPER_PARTITION_SIZE 这里以RK供应商和AML供应商修改为例&#xff1a; &#xff08;1&#xff09;RK改法&#xff1a; 根目录下…

全光谱灯对人体的危害?谨记全光谱灯选购要避开的四大套路

全光谱灯对人体的危害有多大&#xff1f;近年来网上关于护眼台灯对视力有害的言论有很多&#xff0c;引发了很多人空前的关注&#xff0c;事实上这未必是一件坏事&#xff0c;因为随着护眼台灯的热度持续上涨&#xff0c;市面上浑水摸鱼的行为增多了不少&#xff0c;有着不少劣…