vector模拟实现

vector是表示可变大小数组的序列容器

string和vector的区别:vector不支持比较大小  vector不支持+=.+等操作   string结尾有'/0'

find函数

vector函数不提供find函数,因为string要查找字符串,而vector只查找单个字符,所以干脆就不提供find函数了,但是算法库里有find函数,头文件是algorithm,如果找到就返回找到值的位置,如果没找到就返回end位置

基本变量函数

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

reserve函数

我们先看一段错误代码

void reserve(size_t n)
		{
			if (n>capacity())
			{
				
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					memcpy(tmp, _start, sizeof(T) * size());
					delete[] _start;
				}
				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}

要注意size要提前算好,如果等到算_finish时再去算size会导致size求的是新开辟空间(_start被更新了)的size导致错误

但是如果vector里的是string类型的会发生崩溃,主要原因就是memcpy是一个浅拷贝,如图

所以不能用memcpy,进行深拷贝要调用赋值重载进行深拷贝

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

push_back函数

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

【】重载

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

resize函数

void resize(size_t n,const T& val=T())
		{
			if (n < size())
			{
				_finish = _start+n;
			}
			else
			{
				if (n > capacity())
				{
					reserve(n);
				}
					while (_finish != _start+n)
					{
						*_finish = val;
						++_finish;
					}
			}
		}

拷贝构造

template<class InputIterator>
		vector(InputIterator first, InputIterator last)
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}
void swap(vector<T>&  v)const
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);

		}
vector(const vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			vector<T> tmp(v.begin(),v.end());
			swap(tmp);
		}

拷贝构造现代写法和string的拷贝构造类似,但是string有自己的构造函数能让字符串去代工进行拷贝,但是vector只有一个无参的构造函数,所以我们写了一个迭代器版本的构造函数

赋值重载

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

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;
			while (end >= pos)
			{
				*(end) = *(end-1);
				--end;
			}
			*pos=x;
			++_finish;
			return pos;
		}
		vector<int>::iterator pos = find(v.begin(), v.end(), 2);
		if (pos != v.end())
		{
			v.insert(pos, 20);
		}

insert函数会有迭代器失效的问题,主要原因是因为在插入过程中如果增容,会导致pos还在原空间上的位置被释放引发野指针问题,而增容是会开辟新空间的,导致pos找不到,所以我们要更新一下pos。那么我们在传pos位置能不能传引用呢?答案是不能,我们采用传pos位置的返回值来返回,总而言之,insert可能会发生迭代器失效问题,主要看是否发生扩容问题

erase函数

当要求删除所有偶数时

iterator erase(iterator pos)
		{
			assert(pos >= _start);
			assert(pos <= _finish);
			iterator begin = pos + 1;
			while (begin < _finish)
			{
				*(begin - 1) = *begin;
				++begin;
			}
			--_finish;
			return pos;
		}

如果我们想向上面那种代码一样写,会有以上三种情况,原因是当erase完它是返回下一个位置的下标,但是你erase完后又去往后走会导致有的数被跳过了,所以我们应该向下面这样写

	vector<int>::iterator it = v.begin();
		while (it != v.end())
		{
			if (*it % 2 == 0)
			{
				it = v.erase(it);
			}
			else
			{
				++it;
			}
		}

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值