STL_vector

vector<vector> 会实例化两个类
看源代码不能一行一行看
image.png
有了模板之后,内置类型也需要有默认构造函数,所以可以认为内置类型有默认构造函数
迭代器引用不能
image.png
insert之后迭代器失效,有可能野指针
erase之后迭代器失效,结果未定义

匿名对象生命周期只在一行,const&可以延迟生命周期

  • 了解vector容器
  • 熟悉vector的常见接口
  • 常见接口的模拟实现

了解vector容器


1.vector容器
vector是C++标准模板库中的部分内容,vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。  
  • vector内部可以存放内置类型,也可以存放自定义类型。如int,string等
2.vector和string的区别与联系
  1. vector可以存放任意类型的对象,而string只存放char类型的对象
  2. vector的接口比之string接口更为通用,string的某些接口设计是为了更好的操作串
  3. vector和string底层空间都是连续的,本质上都是数组和方法的封装。
3.vector中迭代器

由于底层空间连续,所以原生指针可以作为迭代器使用,同样也可以封装为一个类。VS用的P.J.版本就将string的迭代器封装为一个类,g++用的SGI版本的string迭代器是原生指针。这里模拟实现原生指针版本的。
迭代器失效问题:
vector的迭代器失效常见于insert和erase之后,库中对于insert和erase的函数声明:iterator insert (iterator position, const value_type& val); iterator erase (iterator position);(注:这里只给出一个函数重载版本,详见下面)

  • insert迭代器失效:这里可以看到函数参数为迭代器类型iterator,position为原生指针,插入一个数据之后,如果空间扩容,那么position的位置必会更改,此时在insert之后使用原来的position就会造成野指针问题。
  • erase迭代器失效:如果erase的对象是最后一个元素的话,在源程序中继续使用position,则会

如上,string的insert和erase也会有迭代器失效问题,只是在string中insert和erase函数参数position一般用size_t下标,不用迭代器,故不会出现迭代器失效问题,当然string的insert和erase函数也有迭代器的重载版本,如果用迭代器进行insert和erase,也会出现失效问题。
解决迭代器失效办法:
在每次insert和erase之后,及时更新position,即用函数返回值来更新。但更为建议的是:统一认为insert和erase之后迭代器失效了,不应该使用了。

vector常见接口


std库中vector的声明:
template < class T, class Alloc = allocator<T> > class vector;

  • T:数据类型
  • Alloc:。。。。
一.构造
  1. vector();
    • 默认构造函数
  2. vector(size_t n, const T& val = T());
    • 构造有n个val的vector
  3. vector(const vector& v);
    • 拷贝构造
  4. template<class InputIterator> vector(InputIterator first, InputIterator last);
    • [first, last) 迭代器区间构造
二.运算符重载
  1. vector& operator= (const vector& x);
    • 赋值重载
  2. T& operator[](size_t pos);
    • 方括号重载
三.容量相关
  1. size_t size() const;
    • 有效元素个数
  2. size_t capacity() const;
    • 容器容量
  3. void resize(size_t n, const T& val = T());
    • 如果n>capacity(),则扩容并且用val填充空间
    • 如果n<capacity()且n>size(), 则用val填充空间
    • 如果n<capacity()且n<size(), 则会减少size到n
  4. void reserve(size_t n);
    • n>capacity() ,则扩容,若小于capacity,不变
  5. bool empty() const;
    • vector为空返回true
    • vector不为空返回false
四.元素操作相关
  1. iterator insert(iterator position, const T& val);
    • 在position插入val
  2. iterator insert(iterator position, size_t n, const T& val);
    • 在position插入n个val
  3. iterator erase(iterator position);
    • 删除position位置元素
  4. void push_back(const T& val);
    • 尾插val
  5. void pop_back();
    • 尾删
  6. void swap(vector& v);
    • 交换两个vector
五.迭代器
  1. iterator begin();
    • 返回迭代器起始位置
  2. const_iterator begin() const;
    • 返回const迭代器起始位置
  3. iterator end();
    • 返回迭代器最后一个元素下一个位置
  4. const_iterator end() const;
    • 返回const迭代器最后一个元素下一个位置

接口模拟实现



namespace zs
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

		//如果你提供了构造函数,默认构造函数不在给出
		vector()
		{}

		//在模板中,认为内置类型有默认构造函数,这里由于有一个类模板,防止
		//编译器匹配错误,所以需要重载一个相同参数类型的版本
		vector(size_t n, const T& val = T())
		{
			_begin = new T[n];
			_finish = _begin + n;
			_end_of_storage = _begin + n;

			size_t i = 0;
			for (; i < n; ++i)
			{
				_begin[i] = val;
			}
		}
		vector(int n, const T& val = T())
		{
			_begin = new T[n];
			_finish = _begin + n;
			_end_of_storage = _begin + n;

			size_t i = 0;
			for (; i < n; ++i)
			{
				_begin[i] = val;
			}
		}
		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
		{

			while (first != last)
			{
				
				push_back(*first);
				++first;
			}
		}


		vector(const vector<T>& v)
		{
			reserve(v.capacity());
			
			//不能用memcpy,如果T是自定义类型的话会出错
			size_t i = 0;
			while (i < v.size())
			{
				_begin[i] = v._begin[i];
				++i;
			}

			_finish = _begin + v.size();
			_end_of_storage = _begin + v.capacity();
		}

		T& operator[](size_t pos)
		{
			assert(pos >= 0);
			assert(pos < size());

			return *(_begin + pos);
		}

		const T& operator[](size_t pos) const
		{
			assert(pos >= 0);
			assert(pos < size());

			return *(_begin + pos);
		}
		iterator insert(iterator pos, const T& val)
		{
			assert(pos >= _begin);
			assert(pos <= _finish);
			if (size() + 1 > capacity())
			{
				size_t len = pos - _begin;
				reserve(2 * (capacity() == 0 ? 4 : capacity()));
				pos = _begin + len;
			}

			iterator cur = _finish-1;
			while (pos <= cur)
			{
				*(cur + 1) = *(cur);
				--cur;
			}
			*pos = val;
			++_finish;

			return pos;
		}

		iterator erase(iterator pos)
		{
			assert(pos >= _begin);
			assert(pos < _finish);

			iterator cur = pos + 1;
			while (cur != _finish)
			{
				*(cur-1) = *(cur);
				++cur;
			}
			--_finish;

			return pos;
		}

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

			*_finish = val;
			++_finish;
		}

		void pop_back()
		{
			assert(!empty());

			--_finish;
		}

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

		vector<T>& operator=(vector<T> v)
		{
			std::swap(_begin, v._begin);
			std::swap(_finish, v._finish);
			std::swap(_end_of_storage, v._end_of_storage);

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

				while (_finish != _begin + n)
				{
					*_finish = val;
					++_finish;
				}
				
			}
		}

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
		
				T* tmp = new T[n];
				if (_begin != nullptr)
				{
					size_t i = 0;
					while (i < n)
					{
						tmp[i] = _begin[i];
						++i;
					}
					delete[] _begin;
				}
	

				
				_begin = tmp;
				_finish = _begin + sz;
				_end_of_storage = _begin + n;

			}

		}
		
		size_t size() const
		{
			return _finish - _begin;
		}
		size_t capacity() const
		{
			return _end_of_storage - _begin;
		}
		iterator begin()
		{
			return _begin;

		}
		iterator end()
		{
			return _finish;
		}

		const_iterator begin() const
		{
			return _begin;

		}
		const_iterator end() const
		{
			return _finish;
		}

		~vector()
		{
			delete[] _begin;
			_begin = _finish = _end_of_storage = nullptr;
		}

	private:
		iterator _begin = nullptr;          //起始地址
		iterator _finish = nullptr;         //最后一个有效数据的下一个位置
		iterator _end_of_storage = nullptr; //存储空间末尾的下一个位置
	};

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值