C++-----MySTL实现(6)---vector的实现

1、相关

        前面五个章节都是容器实现的一些基础工作,尤其是迭代器和空间配置器。这两个是实现容器最基础的,一个用来给容器分配空间,一个提供接口以便算法访问容器中的元素。

        vector是动态数组,随着元素的加入内部会自动扩充空间容纳新元素,这也是vector实现的难点。vector是一个连续的线性空间,不管其内部放的是什么元素,使用普通指针均可以作为其迭代器,而vector迭代器所需要的操作,比如:*、->、++、--、+、-、+=、-+等普通指针天生有这些功能,所以vector的迭代器使用普通指针即可。但是其定义还是用之前实现的迭代器的普通接口。

        vector的数据结构很简单,线性的连续空间,用两个迭代器start和finis表示连续空间中已经使用的范围,并用迭代器end_of_storage表示整块连续空间含有备用空间的尾端。vector实际配置的内存比客户需要的会多一些,以备将来扩充,这就是容量的概念。运用这三个迭代器可以很容易的实现vector的一些成员函数,比如begin(),end(),size()等等。

        vector默认使用alloc,二级配置器作为其空间配置器,vector的成员函数涉及到元素的insert或push_back的会比较麻烦,一般会先判断vector是否还有备用空间,如果有,那么之间在备用空间构造元素即可,如果没有就涉及到将源空间的所有数据复制到另一块更大的空间,然后再将需要插入或push的元素加入到vector中。这里就需要注意一个问题,对vector的任何操作,一旦引起空间配置,那么指向原vector的迭代器都会失效。

2、代码

/*
* vector的实现
*/

#ifndef VECTOR_H_
#define VECTOR_H_

#include "allocator.h"
#include <initializer_list>

namespace MySTL
{
	template <class _T, class _Alloc = alloc>  // 默认使用 alloc 为配置器
	class vector
	{
	public:

		typedef _T                 value_type;
		typedef value_type*        pointer;
		typedef const value_type*  const_pointer;
		typedef const value_type*  const_iterator;
		typedef value_type&        reference;
		typedef const value_type&  const_reference;
		typedef size_t             size_type;
		typedef ptrdiff_t          difference_type;
		//注意vector的iterator是原生指针,经过iterator_traits
		//得到迭代器型别是random_access_iterator_category
		typedef value_type*        iterator;

	protected:
		// vector专属空间配置器,每次配置一个元素大小
		typedef simple_alloc<value_type, _Alloc> data_allocator;

		// vector采用简单的线性连续空间。以两个迭代器start和end分别指向头尾,
		// 并以迭代器end_of_storage指向容量尾端。容量(capacity)可能比(尾 - 头 = size)还大,
		// 多余即备用空间。
		iterator start;
		iterator finish;
		iterator end_of_storage;
		//插入操作辅助函数
		void insert_aux(iterator position, const _T& x);
		//释放整个capacity
		void deallocate()
		{
			if (start)
				data_allocator::deallocate(start, end_of_storage - start);
		}

		void fill_initialize(size_type n, const _T& value)
		{
			start = allocate_and_fill(n, value);   // 配置空间并设初值
			finish = start + n;				       // 调整水位
			end_of_storage = finish; 			   // 调整水位
		}
		//以上函数为protected
	public:
		iterator begin() { return start; }
		const_iterator begin() const { return start; }
		iterator end() { return finish; }
		const_iterator end() const { return finish; }
		size_type size() const { return size_type(end() - begin()); }
		size_type max_size() const { return size_type(-1) / sizeof(_T); } //2^32/T
		size_type capacity() const { return size_type(end_of_storage - begin()); }
		bool empty() const { return begin() == end(); }
		reference operator[](size_type n) { return *(begin() + n); }
		const_reference operator[](size_type n) const { return *(begin() + n); }

		//构造函数:
		vector() : start(0), finish(0), end_of_storage(0) {} //空vector
		vector(size_type n, const _T& value) { fill_initialize(n, value); }
		vector(int n, const _T& value) { fill_initialize(n, value); }
		vector(long n, const _T& value) { fill_initialize(n, value); }
		explicit vector(size_type n) { fill_initialize(n, _T()); }
		//拷贝构造函数
		vector(const vector<_T, _Alloc>& x)
		{
			start = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());
			finish = start + (x.end() - x.begin());
			end_of_storage = finish;
		}

		template <class _InputIterator>
		vector(_InputIterator first, _InputIterator last) :
			start(0), finish(0), end_of_storage(0)
		{
			range_initialize(first, last, iterator_category(first));
		}
		//列表构造
		vector(const std::initializer_list<_T>& il)
		{
			range_initialize(il.begin(), il.end(), forward_iterator_tag());
		}

		//析构函数
		~vector()
		{
			destroy(start, finish);  // 全局函式
			deallocate();            // 先前定义好的成员函式
		}

		vector<_T, _Alloc>& operator=(const vector<_T, _Alloc>& x);

		//预留空间:如果要求预留的空间n比原来capacity不大,则不操作
		//否则,将原空间元素完全搬移到新空间
		void reserve(size_type n)
		{
			if (capacity() < n)
			{
				const size_type old_size = size();
				iterator tmp = allocate_and_copy(n, start, finish);
				destroy(start, finish);
				deallocate();
				start = tmp;
				finish = tmp + old_size;
				end_of_storage = start + n;
			}
		}

		// 取出第一个元素内容
		reference front() { return *begin(); }
		const_reference front() const { return *begin(); }
		// 取出最后一个元素内容
		reference back() { return *(end() - 1); }
		const_reference back() const { return *(end() - 1); }
		// 增加一个元素,做为最后元素
		void push_back(const _T& x)
		{
			if (finish != end_of_storage)// 还有备用空间
			{
				construct(finish, x); // 直接在备用空间中建构元素。
				++finish;             // 调整水位高度
			}
			else // 已无备用空间
				insert_aux(end(), x); //交由辅助函数完成
		}

		//交换两个vector
		//实际是指针交换,速度非常快
		void swap(vector<_T, _Alloc>& x)
		{
			std::swap(start, x.start);
			std::swap(finish, x.finish);
			std::swap(end_of_storage, x.end_of_storage);
		}
		//插入操作
		iterator insert(iterator position, const _T& x)
		{
			size_type n = position - begin();
			if (finish != end_of_storage && position == end())//有备用空间且是尾端插入
			{                                                 //不用调整空间布局
				construct(finish, x);// 全局函数。
				++finish;
			}
			else
				insert_aux(position, x);
			return begin() + n;
		}
		iterator insert(iterator position) { return insert(position, _T()); }
		//范围插入操作
		template <class _InputIterator>
		void insert(iterator position, _InputIterator first, _InputIterator last)
		{
			range_insert(position, first, last, iterator_category(first));
		}
		//插入n个相同元素
		void insert(iterator pos, size_type n, const _T& x);
		void insert(iterator pos, int n, const _T& x)
		{
			insert(pos, (size_type)n, x);
		}
		void insert(iterator pos, long n, const _T& x)
		{
			insert(pos, (size_type)n, x);
		}
		//删除最后元素
		void pop_back()
		{
			--finish;
			destroy(finish);//全局函数
		}
		// 将迭代器 position 所指之元素移除
		iterator erase(iterator position)
		{
			if (position + 1 != end()) // 如果 p 不是指向最后一个元素
									   // 将 p 之后的元素整体向前递移
				copy(position + 1, finish, position);

			--finish;           // 调整水位
			destroy(finish);	// 全局函数
			return position;
		}
		// 删除范围内元素
		iterator erase(iterator first, iterator last)
		{
			iterator i = copy(last, finish, first);//待删除范围之后元素整体前移
			destroy(i, finish);	// 全局函数
			finish = finish - (last - first);
			return first;
		}
		// size大小调整:调小——删除后端元素,调大——后端插入值为x的元素
		void resize(size_type new_size, const _T& x)
		{
			if (new_size < size())
				erase(begin() + new_size, end());
			else
				insert(end(), new_size - size(), x);
		}
		void resize(size_type new_size) { resize(new_size, _T()); }
		// 清除全部元素。注意,并未释放空间,以备可能未来还会新加入元素。
		void clear() { erase(begin(), end()); }

	protected:
		iterator allocate_and_fill(size_type n, const _T& x)
		{
			iterator result = data_allocator::allocate(n); // 配置n个元素空间
			try
			{
				uninitialized_fill_n(result, n, x); //全局函数
				return result;
			}
			catch (...)
			{
				// "commit or rollback" 
				data_allocator::deallocate(result, n);
				throw;
			}
		}

		template <class _ForwardIterator>
		iterator allocate_and_copy(size_type n, _ForwardIterator first, _ForwardIterator last)
		{
			iterator result = data_allocator::allocate(n);
			try
			{
				uninitialized_copy(first, last, result);
				return result;
			}
			catch (...)
			{
				// "commit or rollback" 
				data_allocator::deallocate(result, n);
				throw;
			}
		}


		template <class _InputIterator>
		void range_initialize(_InputIterator first, _InputIterator last, input_iterator_tag)
		{
			for (; first != last; ++first)
				push_back(*first);
		}

		// 仅被构造函数调用
		template <class _ForwardIterator>
		void range_initialize(_ForwardIterator first, _ForwardIterator last, forward_iterator_tag)
		{
			size_type n = distance(first, last);
			start = allocate_and_copy(n, first, last);
			finish = start + n;
			end_of_storage = finish;
		}

		template <class _InputIterator>
		void range_insert(iterator pos, _InputIterator first,
			_InputIterator last, input_iterator_tag);

		template <class _ForwardIterator>
		void range_insert(iterator pos, _ForwardIterator first,
			_ForwardIterator last, forward_iterator_tag);

	}; // end of vector

	template <class _T, class _Alloc>
	inline
		bool operator==(const vector<_T, _Alloc>& x, const vector<_T, _Alloc>& y)
	{
		return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
	}

	template <class _T, class _Alloc>
	inline
		bool operator!=(const vector<_T, _Alloc>& x, const vector<_T, _Alloc>& y)
	{
		return !(x == y);
	}

	template <class _T, class _Alloc>
	inline
		bool operator<(const vector<_T, _Alloc>& x, const vector<_T, _Alloc>& y)
	{
		return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
	}

	template <class _T, class _Alloc>
	inline
		bool operator>=(const vector<_T, _Alloc>& x, const vector<_T, _Alloc>& y)
	{
		return !(x < y);
	}

	template <class _T, class _Alloc>
	inline
		bool operator>(const vector<_T, _Alloc>& x, const vector<_T, _Alloc>& y)
	{
		return y < x;
	}

	template <class _T, class _Alloc>
	inline
		bool operator<=(const vector<_T, _Alloc>& x, const vector<_T, _Alloc>& y)
	{
		return !(y < x);
	}

	template <class _T, class _Alloc>
	inline void swap(vector<_T, _Alloc>& x, vector<_T, _Alloc>& y)
	{
		x.swap(y);
	}

	//拷贝赋值运算符
	template <class _T, class _Alloc>
	vector<_T, _Alloc>& vector<_T, _Alloc>::operator=(const vector<_T, _Alloc>& x)
	{
		if (&x != this)  //不是自赋值
		{
			if (x.size() > capacity()) // 如果目标物比我本身的容量capacity还大
			{
				iterator tmp = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());
				destroy(start, finish);	    // 把整个旧的vector 摧毁
				deallocate();			    // 释放旧空间
				start = tmp;				// 设定指向新空间
				end_of_storage = start + (x.end() - x.begin());
			}
			else if (size() >= x.size()) // 如果目标物大小 <= 我的大小size
			{
				iterator i = copy(x.begin(), x.end(), begin());
				destroy(i, finish);
			}
			else //我的size < 目标物大小 < 我的capacity
			{
				copy(x.begin(), x.begin() + size(), start);
				uninitialized_copy(x.begin() + size(), x.end(), finish);
			}
			finish = start + x.size();
		}
		return *this;
	}
	//插入辅助函数,是前面insert和push_back有可能调用
	template <class _T, class _Alloc>
	void vector<_T, _Alloc>::insert_aux(iterator position, const _T& x)
	{
		if (finish != end_of_storage) //还有备用空间
		{
			// 在备用空间起始处建构一个元素,并以vector 最后一个元素值为其初值。    
			construct(finish, *(finish - 1));
			// 调整水位。
			++finish;
			_T x_copy = x;
			copy_backward(position, finish - 2, finish - 1); //插入处之后整体后移一位
			*position = x_copy;
		}
		else // 已无备用空间
		{
			// 配置新空间
			// 配置原则:如果原大小为0,则配置 1(个元素大小);
			// 如果原大小不为0,则配置原大小的两倍,
			// 前半段用来放置原资料,后半段准备用来放置新资料。
			const size_type old_size = size();
			const size_type len = old_size != 0 ? 2 * old_size : 1;

			iterator new_start = data_allocator::allocate(len); // 实际配置
			iterator new_finish = new_start;
			try
			{
				// 将原vector插入点之前的内容拷贝到新vector。
				new_finish = uninitialized_copy(start, position, new_start);
				// 为新元素设定初值x
				construct(new_finish, x);
				// 调整水位。
				++new_finish;
				// 将原vector插入点之后的内容拷贝到新vector。
				new_finish = uninitialized_copy(position, finish, new_finish);
			}
			catch (...)
			{
				// "commit or rollback" 
				destroy(new_start, new_finish);
				data_allocator::deallocate(new_start, len);
				throw;
			}
			// 解构并释放原 vector
			destroy(begin(), end());
			deallocate();
			// 调整迭代器,指向新vector
			start = new_start;
			finish = new_finish;
			end_of_storage = new_start + len;
		}
	}

	// 从 position 开始,安插 n 个元素,元素初值为 x
	template <class _T, class _Alloc>
	void vector<_T, _Alloc>::insert(iterator position, size_type n, const _T& x)
	{
		if (n != 0)// 当 n != 0  才进行以下所有动作
		{
			if (size_type(end_of_storage - finish) >= n)// 备用空间大于等于「新增元素个数」
			{
				_T x_copy = x;
				// 以下计算安插点之后的现有元素个数
				const size_type elems_after = finish - position;
				iterator old_finish = finish;
				if (elems_after > n)// 「安插点之后的现有元素个数」大于「新增元素个数」
				{
					uninitialized_copy(finish - n, finish, finish);
					finish += n;	// 将vector 尾端标记后移
					MySTL::copy_backward(position, old_finish - n, old_finish);
					MySTL::fill(position, position + n, x_copy);// 从安插点开始填入新值
				}
				else// 「安插点之后的现有元素个数」小于等于「新增元素个数」
				{
					uninitialized_fill_n(finish, n - elems_after, x_copy);
					finish += n - elems_after;
					uninitialized_copy(position, old_finish, finish);
					finish += elems_after;
					MySTL::fill(position, old_finish, x_copy);
				}
			}
			else// 备用空间小于「新增元素个数」(那就必须配置额外的内存)
			{
				// 首先决定新长度:旧长度的两倍,或旧长度+新增元素个数
				const size_type old_size = size();
				const size_type len = old_size + max(old_size, n);
				// 以下配置新的vector 空间
				iterator new_start = data_allocator::allocate(len);
				iterator new_finish = new_start;
				try
				{
					// 以下首先将旧vector 的安插点之前的元素复制到新空间
					new_finish = uninitialized_copy(start, position, new_start);
					// 以下再将新增元素(初值皆为 n)填入新空间
					new_finish = uninitialized_fill_n(new_finish, n, x);
					// 以下再将旧vector 的安插点之后的元素复制到新空间
					new_finish = uninitialized_copy(position, finish, new_finish);
				}
				catch (...)
				{
					// commit or rollback
					destroy(new_start, new_finish);
					data_allocator::deallocate(new_start, len);
					throw;
				}
				// 以下清除并释放旧的 vector 
				destroy(start, finish);
				deallocate();
				// 以下调整水位标记
				start = new_start;
				finish = new_finish;
				end_of_storage = new_start + len;
			}
		}
	}



	template <class _T, class _Alloc> template <class _InputIterator>
	void vector<_T, _Alloc>::range_insert(iterator pos, _InputIterator first,
		_InputIterator last, input_iterator_tag)
	{
		for (; first != last; ++first)
		{
			pos = insert(pos, *first);
			++pos;
		}
	}

	template <class _T, class _Alloc> template <class _ForwardIterator>
	void vector<_T, _Alloc>::range_insert(iterator position, _ForwardIterator first,
		_ForwardIterator last, forward_iterator_tag)
	{
		if (first != last)
		{
			size_type n = 0;
			distance(first, last, n);
			if (size_type(end_of_storage - finish) >= n)
			{
				const size_type elems_after = finish - position;
				iterator old_finish = finish;
				if (elems_after > n)
				{
					uninitialized_copy(finish - n, finish, finish);
					finish += n;
					copy_backward(position, old_finish - n, old_finish);
					copy(first, last, position);
				}
				else
				{
					_ForwardIterator mid = first;
					advance(mid, elems_after);
					uninitialized_copy(mid, last, finish);
					finish += n - elems_after;
					uninitialized_copy(position, old_finish, finish);
					finish += elems_after;
					copy(first, mid, position);
				}
			}
			else
			{
				const size_type old_size = size();
				const size_type len = old_size + max(old_size, n);
				iterator new_start = data_allocator::allocate(len);
				iterator new_finish = new_start;
				try
				{
					new_finish = uninitialized_copy(start, position, new_start);
					new_finish = uninitialized_copy(first, last, new_finish);
					new_finish = uninitialized_copy(position, finish, new_finish);
				}
				catch (...)
				{
					destroy(new_start, new_finish);
					data_allocator::deallocate(new_start, len);
					throw;
				}

				destroy(start, finish);
				deallocate();
				start = new_start;
				finish = new_finish;
				end_of_storage = new_start + len;
			}
		}
	}
}// end of MySTL
#endif  //end of VECTOR_H_

3、测试

#include <iostream>
#include "vector.h"

using namespace MySTL;
using std::cout;
using std::endl;

int main()
{
	//test
	vector<int> v1{ 1,2,3 ,5,6,7};
	cout << "Test size capacity" << endl;
	cout << "v1 size: " << v1.size() << " v1 capacity: " << v1.capacity()<<endl;
	//cout << "test push_back insert" << endl;
	cout << endl;
	v1.push_back(8);
	v1.push_back(9);
	v1.insert(v1.begin(), 10);
	v1.insert(v1.begin() +3, 11);
	cout << "after insert push and []:" << endl;
	for (int i = 0; i < v1.size(); ++i) {
		cout << v1[i] << " " ;
	}
	cout << endl;
	cout << endl;
	//test 构造函数
	vector<int> v2 = v1;
	vector<int> v3(v2);
	vector<int> v4(6,9);
	cout << "Test iterator and construct: " << endl;
	
	cout << "v2 value:";
	for (vector<int>::iterator iter = v2.begin(); iter != v2.end(); ++iter) {
		cout << *iter << " ";
	}
	cout << endl;
	cout << "v3 value:" ;
	for (vector<int>::iterator iter = v3.begin(); iter != v3.end(); ++iter) {
		cout << *iter << " ";
	}
	cout << endl;
	cout << "v4 value:" ;
	for (vector<int>::iterator iter = v4.begin(); iter != v4.end(); ++iter) {
		cout << *iter << " ";
	}
	cout << endl;
	//test clear
	cout << endl;
	cout << "Test clear : "<<endl;
	v1.clear();
	cout << "after clear, size of v1: " << v1.size() << " capacity of v1: " << v1.capacity() << endl;
	cout << endl;
	cout << "Test empty(),front(),back(),erase()" << endl;
	cout <<"is v1 empty? "<<v1.empty() <<"is v2 empty()? "<< v2.empty() << endl;
	cout <<"v2.front()= "<< v2.front() << "    v3.front()= " << v3.front() << endl;
	cout << "v2.back()= "<<v2.back() << "   v3.back()= " << v3.back() << endl;
	cout << "after eraster v2.front() :";
		v2.erase(v2.begin());
		cout << "v2.front()= " << v2.front() << endl;
	std::system("pause");
}

4、结果

posted @ 2019-06-04 22:03  吾之求索  阅读(330)  评论(0)    收藏  举报