【C++STL】“vector“容器的模拟实现

这篇具有很好参考价值的文章主要介绍了【C++STL】“vector“容器的模拟实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🎉博客主页:小智_x0___0x_

🎉欢迎关注:👍点赞🙌收藏✍️留言

🎉系列专栏:C++初阶

🎉代码仓库:小智的代码仓库

模拟实现

成员变量

	iterator _start = nullptr;
	iterator _finish = nullptr;
	iterator _endofstorage = nullptr;

这里的iteratortypedef T* iterator;定义来的,T是模板参数。

  • _start是指向开始的指针变量。
  • _finish是指向最后一个元素的下一位的指针变量。
  • _endofstorage是指向当前最大容量处的指针变量。
template <class T>
class vector 
{
public:
	typedef T* iterator;
	typedef const T* const_iterator;
private:
	iterator _start = nullptr;
	iterator _finish = nullptr;
	iterator _endofstorage = nullptr;
};

【C++STL】“vector“容器的模拟实现,C++初阶,c++,stl,容器,vector

构造函数

这里我们模拟实现三种构造函数:

无参构造函数

vector()
	;_start(nullptr)
	,_finish(nullptr)
	,_endofstorage(nullptr)
	{}

直接初始化三个指针变量。

初始化n个val的构造函数

vector(size_t n, const T& val = T())
	; _start(nullptr)
	, _finish(nullptr)
	, _endofstorage(nullptr)
{
	//开空间
	reserve(n);
	//初始化val
	for (size_t i = 0; i < capacity() ; i++)
	{
		_start[i] = val;
	}
	//也可以直接复用resize()
	//resize(n, val);
}

//构造函数重载防止构造时冲突
vector(int n, const T& val = T())
	; _start(nullptr)
	, _finish(nullptr)
	, _endofstorage(nullptr)
{
	//开空间
	reserve(n);
	//初始化val
	for (size_t i = 0; i < capacity(); i++)
	{
		_start[i] = val;
	}
	//也可以直接复用resize()
	//resize(n, val);
}

迭代器区间构造函数


template<class InputIterator>//模板参数
vector(InputIterator first, InputIterator last)
{
	while (first != last)
	{
		push_back(*first);//依次取出解引用并尾插
		++first;
	}
}

拷贝构造

vector(const vector<T>& v)
{
	//new一个capacity大小的空间
	_start = new T[v.capacity()];
	//逐个将值拷贝过去
	for (size_t i = 0; i < v.size(); i++)
	{
		_start[i] = v._start[i];
	}
	//重新写入_finish和_endofstorage的值
	_finish = _start + size();
	_endofstorage = _start + v.capacity();
}

析构函数

~vector()
{
	//如果_start为空的话就不做任何操作
	if (_start)
	{
		//释放_start申请的空间
		delete[] _start;
		//将三个成员变量全部置空
		_start = _finish = _endofstorage = nullptr;
	}
}

begin()

typedef T* iterator;
typedef const T* const_iterator;
//普通类型迭代器
iterator begin()
{
	return _start;
}
//const 迭代器
const_iterator begin() const
{
	return _start;
}

end()

typedef T* iterator;
typedef const T* const_iterator;
//普通迭代器
iterator end()
{
	return _finish;
}
//const 迭代器
const_iterator end() const
{
	return _finish;
}

swap()

void swap(vevtor<T>& v)
{
	//逐个交换每个成员变量
	std::swap(_start, v._start);
	std::swap(_finish, v._finish);
	std::swap(_endofstorage, v._endofstorage);
}

reserve()

void reserve(size_t n)
{
	//判断如果n大于capacity的话就扩容否则不做任何操作
	if (n > capacity())
	{
		//先保存size后面delete之后size()就失效了
		size_t sz = size();
		//new一个n大小的tmp变量
		iterator tmp = new T[n];
		if (_start)//_start不为空进行数据的拷贝
		{
			//for循环逐个拷贝数据
			for (size_t i = 0; i < sz; i++)
			{
				tmp[i] = _start[i];
			}
			//释放之前的数据
			delete[] _start;
		}
		//重新更新三个成员变量
		_start = tmp;
		_finish = tmp + sz;
		_endofstorage = _start + n;
	}
}

这里需要注意的是交换数据的时候不能使用memcpy(tmp, _start, sizeof(T) * sz);
以这段代码为例:

vector<string> v;
v.push_back("11111");
v.push_back("22222");
v.push_back("33333");
v.push_back("44444");

我们来画图理解使用memcpy拷贝的情况>
【C++STL】“vector“容器的模拟实现,C++初阶,c++,stl,容器,vector

  1. memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中
  2. 如果拷贝的是内置类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且 自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。

我们再来画图理解一下逐个拷贝的情况>
【C++STL】“vector“容器的模拟实现,C++初阶,c++,stl,容器,vector
【结论】: 如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是 浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。

resize()

void resize(size_t n, const T& val = T())
{
	//判断是否需要扩容
	if (n < size())
	{
		_finish = _start + n;//n<size()的时候更新_finish的值
	}
	else
	{
		//复用reserve()来调整容量
		reserve(n);
		while (_finish != _start + n)
		{
			//刚刚调整出的空间逐个写入val
			*_finish = val;
			++_finish;
		}
	}
}

capacity()

size_t capacity() const
{
	return _endofstorage - _start;//_endofstorage - _start就是它的最大容量
}

size()

size_t size() const
{
	return _finish - _start;//_finish - _start就是它的元素个数
}

重载[]运算符

普通[]重载:

T& operator[](size_t pos)
{
	//断言检查pos的位置是否合法
	assert(pos < size());
	return _start[pos];//直接return返回
}

const []重载:

const T& operator[](size_t pos) const
{
	assert(pos < size());
	return _start[pos];
}

重载=赋值运算符

vector<T>& operator =(vector<T> v)//形参接收实参会调用拷贝构造,构造出v
{
	//交换*this和v
	swap(v);
	return *this;//返回*this
}

v的作用域在这个函数内,出了函数就会自动析构,我们把*this和v的内容进行了交换,完了出了作用域v也会帮我们析构掉交换之后v的空间。

insert()

iterator insert(iterator pos, const T& x)
{
	assert(pos >= _start && pos <= _finish);//断言检查pos位置的有效性
	if (_finish == _endofstorage)//判断容量是否已经满了
	{
		size_t len = pos - _start;//记录pos前面位置的元素个数
		size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
		reserve(newcapacity);
		// 解决pos迭代器失效问题
		pos = _start + len;
	}
	iterator end = _finish - 1;//记录最后一个元素的位置
	while (end >= pos)//逐个往后挪数据
	{
		*(end + 1) = *end;
		--end;
	}
	*pos = x;//给pos位置赋值x
	++_finish;//对应的_finish也要加1
	return pos;//返回pos位置
}

erase()

iterator erase(iterator pos)
{	
	assert(pos >= _start && pos < _finish);//断言检查pos位置的合法性
	iterator it = pos + 1;//保存pos下一个元素的地址
	while (it != _finish)
	{
		//逐个向前挪动数据
		*(it - 1) = *it;
		++it;
	}
	//对应的再将_dinish的值减1
	--_finish;
	return pos;//返回要删除的下一个位置即为新的pos
}

push_back()

void push_back(const T& x)
{
	//传统写法
	/*if (_finish == _endofstorage)//判断是否需要扩容
	{
		size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
		reserve(newcapacity);
	}
	//给_finish赋值x
	*_finish = x;
	//将_finish加1
	++_finish;*/
	
	//复用insert()给end位置插入x
	insert(end(), x);
}

pop_back()

void pop_back()
{
	//复用erase()先是end()位置减1到最后一个元素的位置
	erase(--end());
}

完整代码

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;

namespace CSDNYYDS {
	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;
		}

		size_t capacity() const
		{
			reutrn _endofstorage - _start;
		}
		size_t size() const
		{
			return _finish - _start;
		}

		vector()
		{}

		vector(size_t n, const T& val = T())
			; _start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			//开空间
			reserve(n);
			//初始化val
			for (size_t i = 0; i < capacity() ; i++)
			{
				_start[i] = val;
			}
			//也可以直接复用resize()
			//resize(n, val);
		}

		vector(int n, const T& val = T())
			; _start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			//开空间
			reserve(n);
			//初始化val
			for (size_t i = 0; i < capacity(); i++)
			{
				_start[i] = val;
			}
			//也可以直接复用resize()
			//resize(n, val);
		}
		//迭代器区间
		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}
		vector(const vector<T>& v)
		{
			_start = new T[v.capacity()];
			for (size_t i = 0; i < v.size(); i++)
			{
				_start[i] = v._start[i];
			}
			_finish = _start + size();
			_endofstorage = _start + v.capacity();
		}
		~vector()
		{
			if (_start)
			{
				delete[] _start;
				_start = _finish = _endofstorage = nullptr;
			}
		}
		void swap(vevtor<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);
		}
		vector<T>& operator =(vector<T> v)
		{
			swap(v);
			return *this;
		}
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				iterator tmp = new T[n];
				if (_start)
				{
					for (size_t i = 0; i < sz; i++)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}
				_start = tmp;
				_finish = tmp + sz;
				_endofstorage = _start + n;
			}
		}

		void resize(size_t n,const T& val=T())
		{
			if (n < size())
			{
				_finsh = _start + n;
			}
			else
			{
				reserve(n);

				while (_finish!=_start+n)
				{
					*_finish = val;
					++_finish;
				}
			}
		}

		void push_back(const T& x)
		{
			insert(end(), x);
		}

		iterator insert(iterator pos, const T& x)
		{
			assert(pos >= _start && pos <= _finish);
			if (_finish == _endofstorage)
			{
				size_t len = pos - _start;

				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);

				// 解决pos迭代器失效问题
				pos = _start + len;
			}
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;
			++_finish;

			return pos;
		}

		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(--end());
		}

		

		T& operator[](size_t pos)
		{
			assert(pos < size());

			return _start[pos];
		}

		const T& operator[](size_t pos) const
		{
			assert(pos < size());

			return _start[pos];
		}


	private:
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _endofstorage = nullptr;
	};
};

动态二维数组的理解

【C++STL】“vector“容器的模拟实现,C++初阶,c++,stl,容器,vector

🍀小结🍀

今天我们认识了C++STL“vector“容器的模拟实现相信大家看完有一定的收获。
种一棵树的最好时间是十年前,其次是现在! 把握好当下,合理利用时间努力奋斗,相信大家一定会实现自己的目标!加油!创作不易,辛苦各位小伙伴们动动小手,三连一波💕💕~~~,本文中也有不足之处,欢迎各位随时私信点评指正!
本节课的代码已上传gitee仓库文章来源地址https://www.toymoban.com/news/detail-575783.html

到了这里,关于【C++STL】“vector“容器的模拟实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • C++ stl容器vector的底层模拟实现

    C++ stl容器vector的底层模拟实现

    目录 前言:   1.成员变量,容量与大小 2.构造函数 无参构造: 带参的使用值进行构造:  使用迭代器区间进行构造: 3.交换 4.拷贝构造 5.赋值重载 6.迭代器 7.扩容 reserve: resize: 8.插入与删除 insert: erase: insert迭代器失效问题: erase迭代器失效问题: 9.头插头删 10.[]重载

    2024年04月15日
    浏览(14)
  • 【C++】:STL源码剖析之vector类容器的底层模拟实现

    【C++】:STL源码剖析之vector类容器的底层模拟实现

    构造一个空vector size和capacity为0 将_start _finish _endofstorage 都置为空指针即可 传统写法 : 1). 新开辟一块和 v 同样容量的空间,更新 _start, _finish, _endofstorage 2). 将 v 中的数据拷贝到新开辟的空间中 注意 : 不要使用memcpy函数拷贝数据,如果数据是内置类型或浅拷贝的自定义类型

    2024年02月04日
    浏览(16)
  • 【STL】模拟实现vector(详解)

    【STL】模拟实现vector(详解)

    2023年05月14日
    浏览(10)
  • 【STL】 模拟实现简易 vector

    【STL】 模拟实现简易 vector

    目录 1. 读源码 2. 框架搭建 3. vector 的迭代器 4. vector 的拷贝构造与赋值 拷贝构造 赋值 5. vector 的常见重要接口实现 operator[ ] 的实现 insert 接口的实现 erase 接口实现 pop_back 接口的实现 resize 接口实现 源码分享 写在最后: 想要自己实现一个 vector,读源码来理解他的实现是必不

    2024年02月16日
    浏览(8)
  • 【STL】vector的模拟实现

    【STL】vector的模拟实现

    目录 前言 结构解析 构造析构 构造 默认构造 初始化成 n 个 val  以迭代器区间构造 拷贝构造 析构 运算符重载 赋值重载 下标访问 迭代器 const迭代器 容量操作 查看大小和容量 容量修改 数据修改 尾插尾删 指定位置插入和删除 insert erase 清空 判空 交换 源码 从vector开始就要开

    2024年02月06日
    浏览(11)
  • 【STL】:vector的模拟实现

    【STL】:vector的模拟实现

    朋友们、伙计们,我们又见面了,本期来给大家解读一下有关vector的模拟实现,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏: C语言:从入门到精通 数据结构专栏: 数据结构 个  人  主  页 : stackY、 C + + 专 栏   : C++ Linux 专

    2024年02月06日
    浏览(8)
  • [STL] vector 模拟实现详解

    [STL] vector 模拟实现详解

    目录 一,准备工作 二,push_back   1, 关于引用 2. 参数const 的修饰  补充 三,迭代器实现 四,Pop_back 五,insert 1. 补充——迭代器失效 六, erase 七,构造函数  1. 迭代器构造  2. 其他构造 3. 拷贝构造  1) 传统写法 2)现代写法(提高函数复用性)  八,赋值符号重载 九,

    2024年02月16日
    浏览(11)
  • 【C++ STL】vector模拟实现

    【C++ STL】vector模拟实现

    2023年05月17日
    浏览(31)
  • C++ STL vector 模拟实现

    C++ STL vector 模拟实现

    ✅1主页:我的代码爱吃辣 📃2知识讲解:C++之STL 🔥3创作者:我的代码爱吃辣 ☂️4开发环境:Visual Studio 2022 💬5前言:上次我们已经数字会用了vector,这次我们对其底层更深一步挖掘,其中重点是,Vector中一些深浅拷贝问题。 目录 一.Vector模拟实现的整体框架 二. Vector的构

    2024年02月13日
    浏览(20)
  • C++ [STL之vector模拟实现]

    C++ [STL之vector模拟实现]

    本文已收录至《C++语言》专栏! 作者:ARMCSKGT vector是STL容器容器之一,其底层实现类似于数据结构顺序表,相当于string来说得益于泛型模板的加持使得vector可以变为任何类型,且是可以动态扩容,堪称大号数组!在vector的实现中,有许多值得我们学习的细节,接下来将为大家

    2024年02月11日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包