vector的模拟实现

vector的成员变量

  • _start:指向元素开始的位置
  • _finish:指向最后一个元素的下一个位置
  • _endofstorage:指向从堆区开辟的空间的末尾的下一位置
    在这里插入图片描述
template<class T>
	class vector
	{
	public:
		//迭代器
		typedef T* iterator;
		typedef const T* const_iterator;
		//反向迭代器迭代器
		typedef reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
		typedef reverse_iterator<iterator, T&, T*> reverse_iterator;
		//、、、、、、
		//各种成员函数
		//、、、、、、
	private:
		iterator  _start;
		iterator _finish;
		iterator _endofstorage;
};

构造函数

1、无参构造

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

2、采用迭代器的构造方法

template<class InputerIterator>//新建一个模板参数是为了可以传多种迭代器,而不是只能传vector的迭代器
		vector(InputerIterator first, InputerIterator last)//vector有一种构造方法是vector v(v1.begin(),v1.end())
			:_start(nullptr)
			,_finish(nullptr)
			,_endofstorage(nullptr)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}

		}

3、拷贝构造

		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);
		}

		vector(const vector<T>& v)//拷贝构造必需传引用,如果不传引用,就是传值,传值又是一次拷贝构造,进而死循环,所以不能像operator=那样写。
			:_start(nullptr)
			,_finish(nullptr)
			,_endofstorage(nullptr)
		{
			vector<T> tmp(v.begin(), v.end());
			swap(tmp);
		}

赋值运算符重载

		vector<T>& operator=(vector<T> v)
		{
			swap(v);
			return *this;
		}

析构函数

		~vector()
		{
			if (_start)
			{
				delete[] _start;//销毁所开辟的所有空间
				_start = _finish = _endofstorage = nullptr;
			}
		}

reverse()扩容

size_t size() const
{
	return _finish - _start;//指针-指针,因为同类型得到的是这段空间的元素的个数。
}
		
void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)//_start不为空,说明原来有数据,要拷贝
				{
					//memcpy是浅拷贝,当T是string时,字符串是存在堆中的,string只存了指向这个字符串的指针、size、capacity。
					//因此使用memcpy也只是把指针的地址重新赋值给了tmp,当delete[] _start;就已经销毁了字符串的空间。
					//然后tmp又赋值给了_start,程序结束,调用析构函数,又要再次销毁字符串的空间,同一块空间被释放了2次,程序错误
					//因此不能使用memcpy
					//memcpy(tmp, _start, sizeof(T) * size());//大部分情况是对的,但是涉及深拷贝问题会有错误
					for (size_t i = 0; i < sz; i++)
					{
						//相当于string =string 调用了string类中的operator=,operator是深拷贝。
						tmp[i] = _start[i];
					}
					delete[] _start;
				}
				_start = tmp;
				// _finish = _start + size();这句代码有误,因为_start的位置改了,所计算的size也是错的,应该提前保存原来数组的大小,即sz
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}

push_back

当_finish == _endofstorage说明空间不够需要扩容。
在这里插入图片描述

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

resize()

void resize(size_t n, const T& val = T())//const &会延长匿名对象的生命周期,延长到整个作用域,而不是仅是这一行代码
		{
			if (n < size())//如果定义的空间比原来还要小,即让finish指向_start+n的位置,而不用销毁空间
			{
				_finish = _start+n;
			}
			else
			{

				if (n > capacity())//定义的n大于容量了,扩容
				{
					reserve(n);
				}

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

			}
		}

insert

		iterator insert(iterator pos, const T& x)//传迭代器是规定,看文档;返回值要返回新插入元素位置的迭代器,也是为了处理迭代器失效问题
		{
			assert(pos >= _start);
			assert(pos <= _finish);
			if (_finish == _endofstorage)
			{
				// 扩容会导致pos失效,扩容需要更新一下pos,因为扩容可能是异地扩容
				size_t len = pos - _start;
				reserve(capacity() == 0 ? 4 : (capacity() * 2));
				pos = _start + len;
			}
			iterator end = _finish - 1;
			//这个while循环是将数据往后挪一个位置
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;
			_finish++;
			return pos;
		}

erase

iterator erase(iterator pos)
		{
			assert(pos >= _start);
			assert(pos < _finish);//这里不能用=,因为可能要删除最后一个元素
			iterator begin = pos + 1;//让pos后一个元素 覆盖 pos位置上的元素
			while (begin < _finish)
			{
				*(begin - 1) = *begin;
				begin++;
			}
			--_finish;
			return pos;
		}
		

剩余的简单成员函数

		void pop_back()//尾删
		{
			assert(_finish > _start);

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

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

		size_t capacity() const//返回容量大小
		{
			return  _endofstorage- _start;
		}

正向迭代器


		const_iterator begin() const
		{
			return _start;
		}

		const_iterator end() const
		{
			return _finish;
		}

		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}

反向迭代器

方向迭代器的rbegin在正向迭代的end上,反向迭代器rend在正向迭代器的begin上。

		reverse_iterator rbegin()
		{
			return reverse_iterator(end());
		}

		reverse_iterator rend()
		{
			return reverse_iterator(begin());
		}

我们为反向迭代器新建了一个类

namespace Lgc
{
	//反向迭代器的end就是正向迭代器的begin,反向迭代器的begin就是正向迭代的end,这样写是为了复用正向迭代器
	//因为用的是模板,这个反向迭代器同时也可以给其他容器使用。(如vector)
	template<class Iterator,class Ref,class Ptr>
	class reverse_iterator
	{
	
		typedef reverse_iterator<Iterator, Ref, Ptr> self;
		
	public:
		reverse_iterator(Iterator it)
			:_it(it)
		{

		}

		Ref operator*()
		{
			Iterator prev = _it;//prev不能是self类型,因为如果是self则prev是个反向迭代器,--还是一个反向迭代器,在*就是调用自己的operator*,然后一直调用自己的operator*,直到栈溢出(3.15 2:41:45) 我们的本意是去调用正向迭代器的operator*
			return *(--prev);//因为rbegin在正向迭代器的end上,而end的位置在_finish的位置上,要获取元素,所以要--
		}

		Ptr operator->()
		{
			return &(operator*());
		}

		self& operator++()
		{
			--_it;
			return *this;
		}

		self operator++(int)
		{
			self tmp(*this);
			--_it;
			return tmp;
		}

		self& operator--()
		{
			++_it;//因为是反向迭代的原因,--在逻辑是就是++
			return *this;
		}

		bool operator!= (const self& rit) const
		{
			return _it != rit._it;//这个不等于是调用了正向迭代器的运算符重载!=
		}

	private:
		Iterator _it;
	};
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值