c++初阶-----STL---vector模拟

作者前言

🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
​🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言、C++和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂


vector的模拟实现

STL源码
我们可以查看里面的vector的源码,
我们可以发现有三个
在这里插入图片描述

  iterator start;
  iterator finish;
  iterator end_of_storage;

大概意思就是
在这里插入图片描述

下面我们来简单模拟一些常用的成员函数,其中需要注意的就是扩容的话,我这里采用的是两倍扩容,

namespace bit
{
	template <typename T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		vector()

		{
			_start = nullptr;
			_finish = nullptr;
			_end_of_storage = nullptr;
		}
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				T* tmp = new T[n];
				if(_start)
					memcpy(tmp, _start, sizeof(T) * n);
				_finish = tmp + size();
				delete[] _start;
				_start = tmp;
				_end_of_storage = _start + n;
			}
		}
		
		void push_back(const T& a)
		{
			if (_finish == _end_of_storage)
			{
				//扩容
				size_t newcapacity = size() > 0 ? 2 * size() : 4;
				reserve(newcapacity);
			}
			*_finish = a;
			_finish++;
		}
		size_t size()
		{
			return _finish - _start;
		}
		size_t capacity()
		{
			return _end_of_storage - _start;
		}
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
	private:
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;
	};
}

这些成员函数是比教常用的,这里只是简单的模拟一下,有兴趣的话可以去看看STL源码
需要注意的模拟的reserve是这样的写法只适用于一些内置类型如, int 、char…,,
如果是自定义类型的话,就拿
vector<string> 来说,
在这里插入图片描述
在reserve中使用memcpy来进行,会导致拷贝的string(),指向的空间是一个野指针,我们可以构造一个析构函数,采用引用计数法来决定这块空间是否释放,或者我们自己写一个赋值的方法来 解决

赋值的方法:

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				T* tmp = new T[n];
				if (_start)
					//memcpy(tmp, _start, sizeof(T) * n);
				{
					for (int i = 0; i < size(); i++)
					{
						tmp[i] = (*this)[i];
					}
				}
				_finish = tmp + size();
				delete[] _start;
				_start = tmp;
				_end_of_storage = _start + n;
			}
		}

insert模拟

	void insert(size_t pos, const T& content)
		{
			assert(pos <= size());
			if (_finish == _end_of_storage)
			{
				//扩容
				size_t newcapacity = size() > 0 ? 2 * size() : 4;
				reserve(newcapacity);
			}
			//后移
			bit::vector<T>::iterator then = _finish;
			while (_finish >= _start + pos)
			{
				*(_finish + 1) = *(_finish);
				_finish--;
			}
			_finish = then + 1;
			*(_start + pos) = content;

		}
		void insert(iterator pos, const T& content)
		{
			assert(pos>=_start && pos <= _finish);
			if (_finish == _end_of_storage)
			{
				//扩容
				size_t newcapacity = size() > 0 ? 2 * size() : 4;
				reserve(newcapacity);
			}
			size_t postion = (pos - _start) / sizeof(T);//记录pos的相对位置,因为pos位置可能被释放了
			//后移
			bit::vector<T>::iterator then = _finish;
			while (_finish >= _start + postion)
			{
				*(_finish + 1) = *(_finish);
				_finish--;
			}
			_finish = then + 1;
			*(_start + postion) = content;

		}

这里我模拟了两个,一个是通过下标的,一个是通过迭代器的
需要注意的是迭代器这个,
在这里插入图片描述
迭代器这个在开辟新的地址的时候,会把原来的空间释放掉,pos也就成为了野指针,因此,我们只需进行计算出原来的pos的相对位置,然后在新的地址上找出相对应的位置就行,

erase模拟

	void erase(iterator postion)
		{
			assert(postion >= _start && postion < _finish);
			while (postion+1 < _finish)
			{
				*postion = *(postion + 1);
				postion++;
			}
			_finish = postion;
		}

		void erase(iterator first,iterator last)
		{
			assert(first >= _start && last <= _finish);
			iterator postion1 = first;
			iterator postion2 = last;
			while (postion2 < _finish)
			{
				*postion1 = *(postion2);
				postion1++;
				postion2++;
			}
			_finish = postion1;
		}

这里简单的模拟一下,

迭代器失效

在上面的模拟的insert的函数中就有这个情况,
在这里插入图片描述
使用reserve是有可能使_start改变的,跟c语言的realloc是一样的,开辟一块新的空间,我这里模拟的pos是一个下标,不是迭代器,如果pos是一个迭代器,那么就有可能指向的地址早已经被释放掉了,改变这块地址的内容,没有意义,所以我们只能找到对应位置来修改,这是一种解决内部的迭代器失效,
外部的迭代器失效还是会存在, 一般有这种情况,我们不会使用外面的迭代器,因为那是没有意义的.

还要一些情况

在这里插入图片描述
在vs中使用erase删除,it就会失效的,这个由编译器导致的,不同的编译器有不同的,还有就是earse本身删除数据会不会缩容,也是编译器决定的,如果缩容了,_start也会有可能改变,it也就会失效

总结: 迭代器失效一般情况是野指针,或者指向的那块地址不属于原来的那块开辟的空间,

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老秦包你会

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值