STL——Vector详解

目录

vector结构

构造函数

默认构造

迭代器区间构造

拷贝构造 

赋值重载 

析构函数 

容量大小相关函数 

 size

capacity

empty 

reserve 

resize

operator[] 

迭代器 

反向迭代器实现 

 迭代器实现

修改相关函数 

push_back

pop_back

insert 

实现

迭代器失效

erase

实现

迭代器失效 


vector结构

这里vector底层采用迭代器实现

        template<class T>
        typedef T* iterator;
		typedef const T* const_iterator;
private:
		iterator _start;
		iterator _finish;
		iterator _endofstorage;

构造函数

默认构造

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

		}
       

迭代器区间构造

 //迭代器区间初始化
		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}

拷贝构造 

这里拷贝构造采用现代写法,用迭代器区间初始化一个tmp对象,然后交换。

需要注意的是这里的拷贝构造一定要使用初始化列表进行初始化!否则交换中会含有随机值,临时对象被销毁时会因为随机值造成程序崩溃!

        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)
			:_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;
			}
		}

容量大小相关函数 

 size

返回有效数据个数

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

capacity

返回容量大小

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

empty 

判空

        bool empty()const
		{
			return _start == _finish;
		}

reserve 

扩容

这里扩容后如果使用memcpy拷贝数据,对于自定义类型而言将会造成浅拷贝问题!

        void reserve(size_t n)
		{
			if (n > capacity())
			{
				T* tmp = new T[n];
				size_t sz = size();
				//memcpy(tmp, _start, sizeof(T) * sz);
				//这里如果使用memcpy拷贝数据
				//如果vector存的是自定义类型数据,
				//可能造成浅拷贝问题,即一块空间析构两次!
				if (_start)
				{
					for (size_t i = 0; i < sz; i++)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}
				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}

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++;
				}
			}
		}

operator[] 

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

迭代器 

反向迭代器实现 

反向迭代器由正向迭代器组成,然后对其操作进行重载,这种结构对于其他容器而言都是通用的,

体现了泛型编程的优势。

    template <class Iterator,class Ref,class Ptr>
	class _reverse_iterator
	{
	public:
		typedef _reverse_iterator<Iterator, Ref, Ptr> self;
		_reverse_iterator(const Iterator& it)
			:_it(it)
		{
		}
		Ref operator*()
		{
			Iterator prev = _it;
			return *--prev;
		}
		Ptr operator->()
		{
			return &(operator*());
		}
		bool operator==(const self& rit)
		{
			return _it == rit._it;
		}
		bool operator!=(const self& rit)
		{
			return _it != rit._it;
		}
		self& operator++()
		{
			_it--;
			return *this;
		}
		self operator++(int)
		{
			self tmp(*this);
			_it--;
			return tmp;
		}
		self& operator--()
		{
			_it++;
			return *this;
		}
		self operator--(int)
		{
			self tmp(*this);
			_it++;
			return tmp;
		}
	private:
		Iterator _it;
	};

 迭代器实现

        typedef T* iterator;
		typedef const T* const_iterator;
		typedef _reverse_iterator<iterator, T&, T*> reverse_iterator;
		typedef _reverse_iterator<const_iterator,const T&, const T*>     const_reverse_iterator;
		reverse_iterator rbegin()
		{
			return reverse_iterator(end());
		}
		reverse_iterator rend()
		{
			return reverse_iterator(begin());
		}
		const_reverse_iterator rbegin()const
		{
			return const_reverse_iterator(end());
		}
		const_reverse_iterator rend()const
		{
			return const_reverse_iterator(begin());
		}
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
		const_iterator begin()const
		{
			return _start;
		}
		const_iterator end()const
		{
			return _finish;
		}

修改相关函数 

push_back

尾插

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

pop_back

尾删

        void pop_back()
		{
			assert(_start != _finish);
			_finish--;
		}

insert 

实现

        iterator insert(iterator pos, const T& val)//返回新插入元素位置
		{
			//确保位置合法
			assert(pos <= _finish);
			assert(pos >= _start);
			//保存位置,以防扩容后迭代器失效!
			size_t len = pos - _start;
			if (_finish == _endofstorage)
			{
				reserve(capacity() == 0 ? 4 : capacity() * 2);
				pos = _start + len;//扩容后要更改pos的位置!
			}
			iterator end = _finish;
			while (end > pos)
			{
				(*end) = *(end - 1);
				end--;
			}
			*pos = val;
			_finish++;
			return pos;
		}

迭代器失效

insert中如果发生扩容,那么pos位置将会发生改变,要更新pos的位置,所以一开时计算一下pos的相对位置,如果发生扩容就更新!

插入后,如果继续使用当前迭代器而且没有接受返回值,将导致插入位置及后面元素迭代器失效!

当然,如果你插入后不使用迭代器,也就不会引发问题。

erase

实现

        iterator erase(iterator pos)//返回被删除元素后一个元素的位置
		{
			assert(pos >= _start);
			assert(pos < _finish);
			iterator begin = pos + 1;
			while (begin != end())
			{
				*(begin-1) = *begin;
				begin++;
			}
			_finish--;
			return pos;
		}

迭代器失效 

这里使用删除偶数场景:

场景1:1 2 3 4 崩溃

场景2:1 2 3 4 5 正常

场景3: 1 2 4 3 剩下1 4 3   没有删完

 原因:erase后,后面的元素前移,导致错位。

而在某些环境下,对于迭代器失效的检查非常严格,如果erase后不接受返回值,又对迭代器进行操作,将会造成程序运行报错

正确使用:

    void erasenumber()//删除偶数
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		//v1.push_back(5);
		vector<int>::iterator it = v1.begin();
		while (it != v1.end())
		{
			//vs下对于迭代器失效的检查非常严格
			//如果不接受返回值,那么就会引发失效问题,程序直接报错
			if (*it % 2 == 0)
			{
				it = v1.erase(it);
			}
			else
			{
				it++;
			}
		}
		for (auto x : v1)
		{
			cout << x << ' ';
		}
	}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嚞譶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值