C++——vector类及其模拟实现

2024-04-01 1170阅读

前言:前边我们进行的string类的方法及其模拟实现的讲解。这篇文章将继续进行C++的另一个常用类——vector。


一.什么是vector

vector和string一样,隶属于C++中STL标准模板库中的一个自定义数据类型,实际上就是线性表。两者之间有着很多相似,甚至相同的方法。

但是它们也有着很大的不同:因为vector是线性表,所以他可以存储任意类型的数据,甚至是自定义类型的数据,包括vector本身。


二.vector基本框架

#include
namespace Myvector
{
	template
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		//构造函数
		voctor()
		{}
		//析构函数
		~voctor()
		{
			delete[] _start;
			_strat = _finish = _endofstorage = nullptr;
		}
		//迭代器
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
		const_iterator begin() const
		{
			return _start;
		}
		const_iterator end() const
		{
			return _finish;
		}
		//数据个数
		size_t size() const
		{
			return _finish - _start;
		}
		//空间大小
		size_t capacity() const
		{
			return _endofstorage - _start;
		}
		//[]运算符重载
		T& operator[](size_t pos)
		{
			assert(pos  

因为vector允许定义不同类型的数据,所以我们要使用模版来定义类。

值得注意的是,在voctor中我们不用传统的size和capacity来定义数据个数和总空间大小,而是都将它们定义为指针类型,通过指针间的相减来得到size和capacity。初始情况下三者均为空指针。

同时我们将T*指针类型重定义为iterator,这是因为vector的本质就是数组,其迭代器就是指针。


三.vector常用操作

1.扩容

扩容分为两种方式,只扩容不初始化的reserve,以及扩容并且初始化的resize调整:

		//扩容
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t old_size = size();
				T* tmp = new T[n];
				//memcpy(tmp, _start, sizeof(T) * size());
				for (size_t i = 0; i  

扩容较为简单,值得注意的是这里不在使用strcpy,而是通过for循环的方式进行赋值。

		//调整
		void resize(size_t n,const T& val = T())
		{
			if (n > size())
			{
				reserve(n);
				while (_finish  

对于resize,因为我们需要使用缺省参数,但是由于vector的对象类型不定,甚至是自定义类型,所以我们不能使用0作为缺省参数,而应使用匿名对象作为参数,让匿名对象去自动识别类型并调用自己的构造函数形成初始值。


2.插入

先来看尾插,与string类似,需要考虑扩容:

		//尾插
		void push_back(const T& val)
		{
			if (_finish == _endofstorage)
			{
				reserve(capacity() == 0 ? 4 : capacity() * 2);
			}
			*_finish = val;
			_finish++;
		}

测试如下:

C++——vector类及其模拟实现

 在来看指定位置的插入,先判断pos是否合法,同样需要判断扩容:

		//指定位置插入
		void insert(iterator pos, const T& val)
		{
			assert(pos >= _start);
			assert(pos = pos)
			{
				*(it + 1) = *it;
				--it;
			}
			*pos = val;
			_finish++;
		}

这个指定的位置pos用迭代器比用数字更加方便进行比较,所以建议直接使用迭代器进行插入。

有一点值得注意的是,传入的pos是指向原数组的,如果进行了扩容,那么原数组被销毁,所有的指针都指向新的数组,所以也需要对pos指针进行更新,否则pos就会成为野指针。 

 测试如下:

C++——vector类及其模拟实现


3.遍历

除了上边的for循环遍历外,我们还可以通过迭代器和范围for进行遍历:

		vector::iterator it = v.begin();
		while (it != v.end())
		{
			cout 
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]