【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;//指向动态开辟数组的末尾
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

时尚新选择,小塔RFID技术重塑样衣管理

在时尚领域&#xff0c;样衣是创意与工艺的完美结合&#xff0c;每一件都承载着设计师的心血与期待。然而&#xff0c;当这些珍贵的样版在传统的管理体系下流转时&#xff0c;样版管理成为一个令人头疼的问题。手动记录、盘点和样板追溯成为常态&#xff0c;但这种方式容易出错…

机器学习(二)之监督学习

前言&#xff1a; 上一节大概讲解了几种学习方式&#xff0c;下面几张就具体来讲讲监督学习的几种算法。 以下示例中和都是权重的意思&#xff01;&#xff01;&#xff01; 注&#xff1a;本文如有错误之处&#xff0c;还请读者指出&#xff0c;欢迎评论区探讨&#xff01; 1…

17. map和set的模拟实现(也就是用红黑树封装map和set)

1.map和set底层调用的红黑树的实现 有不清楚的地方&#xff0c;参考AVL树的模拟实现和红黑树的模拟实现 红黑树迭代器的实现 // 红黑树迭代器的类模板 template<class T, class Ref, class Ptr> struct __RBTreeIterator {// 将红黑树节点的类类型定义为Nodetypedef R…

绽放新笑容:儿童换牙期的关怀与注意

引言&#xff1a; 儿童的换牙期是成长过程中的重要阶段&#xff0c;标志着他们逐渐迈向成人世界。然而&#xff0c;伴随着牙齿的脱落和新牙的生长&#xff0c;孩子们可能会经历一些不适和困扰。本文将探讨儿童换牙期的注意事项&#xff0c;以帮助家长和孩子们度过这一特殊时期&…

扎根理论分析原理、方法与Nvivo技术应用

扎根理论越来越流行&#xff0c;成为经常被采用的研究方法之一。扎根理论的研究者来自广泛的研究领域&#xff0c;例如社会工作、护理、医药、综合医疗保健、教育、管理和商业。这些从业者和学者试图从他们所在学科范围内解释行为模式。对于扎根理论本质和实践的研究引发了知名…

这个表格为什么在VS Code里面预览可以显示,在浏览器预览就没有显示

在VS Code里面预览可以显示如图&#xff1a; 在浏览器预览就不能显示了&#xff0c;刚开始还好的后来不知道弄错了哪里了&#xff0c;哭死 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"vi…

Swagger:在线接口文档

Swagger介绍及使用 官网:https://swagger.io/ 介绍 使用Swagger你只需要按照它的规范去定义接口及接口相关的信息&#xff0c;就可以做到生成接口文档&#xff0c;以及在线接口调试页面。 Knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案。 使用方式 1.导入 kni…

qt5-入门-QListWidget-通过右键快捷菜单复制item内容

参考&#xff1a; C GUI Programming with Qt 4, Second Edition 本地环境&#xff1a; win10专业版&#xff0c;64位&#xff0c;Qt5.12 效果 在某个item上右键&#xff0c;点击copy后&#xff0c;item的内容已复制到剪贴板。 实现 #include <QMenu> #include <…

如何用微信发布考试成绩(如月考、期中、期末等)

自教育部《未成年人学校保护规定》颁布后,教育部明确表示:学校不得公开学生的考试成绩、排名等信息!同时学校应采取措施,便利家长知道学生的成绩等学业信息,对于教师来说,如何用微信发布考试成绩(如:月考、期中、期末等)就成了一道难题... 公开吧,会伤害到学生自尊心,甚至被投诉…

创建钉钉审批流实例

1、依赖 <!--钉钉 api --> <dependency><groupId>com.aliyun</groupId><artifactId>dingtalk</artifactId><version>2.0.14</version> </dependency> <!--钉钉 事件订阅--> <dependency><groupId>co…

CUDA编程技术概述

CUDA&#xff08;Compute Unified Device Architecture&#xff0c;统一计算设备架构&#xff09;是由英伟达&#xff08;NVIDIA&#xff09;公司推出的一种软硬件集成技术&#xff0c;是该公司对于GPGPU&#xff08;通用图形处理器计算&#xff09;的正式名称。透过这个技术&a…

Levenberg-Marquardt (LM) 算法进行非线性拟合

目录 1. LM算法2. 调包实现3. LM算法实现4. 源码地址 1. LM算法 LM算法是一种非线性最小二乘优化算法&#xff0c;用于求解非线性最小化问题。LM主要用于解决具有误差函数的非线性最小二乘问题&#xff0c;其中误差函数是参数的非线性函数&#xff0c;需要通过调整参数使误差函…

eNSP学习——静态路由及默认路由基本配置

目录 知识背景 实验目的 实验步骤 实验内容 实验拓扑 实验编址 实验前期准备 实验步骤 1、基本配置&#xff08;按照实验编址设置好对应的IP地址&#xff09; 2、是实现主机之间的通信 3、实现全网全通来增强网络的可靠性 4、使用默认路由实现简单的网络优化 需要各…

HTB靶场 Perfection

端口 打开了ssh和http服务 访问 Perfection靶机的网站 是一个根据权重计算总成绩的网站 Wappalyzer查看网页用的什么编写搭建的 抓包看一下是怎么工作的 发送,&#xff0c;返回的结果 如果我在 类别 后面多加一句命令 就会出现提示 恶意输入阻止 大概率有命令注入 通过插件…

解决宏定义后面无法加分号

总结&#xff1a;注意是针对单行if语句使用&#xff0c;并且宏定义后面必须带分号&#xff08;格式统一&#xff09; 参考连接 C语言种do_while(0)的妙用_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1vk4y1R7VJ/?spm_id_from333.337.search-card.all.click&vd_…

2万8金句美句格言签名句子ACCESS\EXCEL数据库

优美句子类的数据已经有《33万多优美句子经典句子ACCESS数据库》、《近2万签名的句子网络签名ACCESS数据库》、《24万QQ伤感签名微信签名ACCESS数据库》、《2万多条QQ签名论坛签名大全ACCESS数据库》&#xff0c;今天又遇到一个&#xff0c;感觉也很不错&#xff0c;发上来看看…

pip安装的python包放在哪里了?—— ubuntu系统

1 pip 安装了哪些包 2 包安装在哪里了 thirty-twott:~/Desktop$ pip show openai Name: openai Version: 1.19.0 Summary: The official Python library for the openai API Home-page: Author: Author-email: OpenAI <supportopenai.com> License: Location: /ho…

Cairo

文章目录 关于 Cairo 关于 Cairo 官网&#xff1a;https://cairographics.org官方文档&#xff1a;https://cairographics.org/documentation/ Cairo是一个支持多个输出设备的2D图形库。 当前支持的输出目标 包括 X Window System&#xff08;通过Xlib 和 XCB&#xff09;、Qu…

Gartner发布攻击面管理创新洞察:CTEM、VA、EASM、CAASM、ASA、DRPS、BAS、VM等攻击面管理相关技术及关系

安全运营团队负责管理跨内部和外部数字资产的复杂攻击面。这项研究概述了攻击面评估空间&#xff0c;以帮助安全和风险管理领导者驾驭技术并改善其安全状况。 主要发现 随着本地和云中的技术环境变得越来越复杂和分散&#xff0c;组织必须管理不断增长的攻击面。 SaaS 应用程序…

wordpress 突然报错Error establishing a database connection

wordpress 突然报错Error establishing a database connection 通过在宝塔端多种方式检测测&#xff0c;查看到时Mysql服务挂了&#xff0c;重启Mysql即可