Vector.h

#pragma once

#include "Alloc.h"
#include "Uninitialized.h"
#include <assert.h>

//vector采用的数据结构就是线性连续空间
template<class T,class Alloc = alloc>
class Vector
{
public:
	//嵌套型别
	typedef T* Iterator;
	typedef T ValueType;
	typedef T* Pointer;
	typedef T& Reference;
	typedef ptrdiff_t DifferenceType;

	typedef const T* ConstPointer;
	typedef const T* ConstIterator;
	typedef const T& ConstReference;

protected:
	typedef SimpleAlloc<ValueType, Alloc> DataAllocator;
	typedef Vector<T> Self;
	T* _start;       //表示目前使用空间的头
	T* _end;         //表示目前使用空间的尾
	T* _endOfStorage;//表示目前可用空间的尾
public:
	Vector()
		:_start(NULL)
		, _end(NULL)
		, _endOfStorage(NULL)
	{}
	Vector(size_t n, const T& value)//构造函数,指定Vector大小并填充初值
	{
		FillInitializen(n, value);
	}
	void FillInitializen(size_t n,const T& value)
	{
		_start = AllocateAndFill(n,value);
		_end = _start + n;
		_endOfStorage = _end;
	}
	Iterator AllocateAndFill(size_t n,const T& value)
	{
		Iterator result = DataAllocator::Allocate(n);//分配空间
		//UninitializedFill(result,n,value);
		return result;
	}

	~Vector()
	{}
	Iterator Begin()
	{
		return _start;
	}
	ConstIterator Begin()const
	{
		return _start;
	}
	Iterator End()
	{
		return _end;
	}
	ConstIterator End()const
	{
		return _end;
	}
	Reference Front()
	{
		return *Begin();
	}
	ConstReference Front()const
	{
		return *Begin();
	}
	Reference Back()
	{
		return *(End() - 1);
	}
	ConstReference Back()const
	{
		return *(End() - 1);
	}
	void PushBack(const T& x)
	{
		Insert(End(),x);
	}
	void PopBack()
	{
		if (_start != _end){
			--_end;//表示放弃尾部元素
			Destroy(_end);
		}
	}
	//iterator insert(iterator position);
	//iterator insert(iterator position, const T& x);
	//void insert(iterator position, InputIterator first, InputIterator last);
	//void insert(iterator position,const_iterator first, const_iterator last);
	//void insert(iterator pos, size_type n, const T& x);
	//void insert(iterator pos, int n, const T& x);
	//void insert(iterator pos, long n, const T& x);
	Iterator Insert(Iterator pos,const T& x)
	{
		//以下配置原则:如果原大小为0,则配置1个元素的大小
		//             否则,配置原大小的两倍
		size_t n = pos - _start;
		size_t oldsize = Size();
		if (_start == _endOfStorage){//1、此时没有一个数据,可用空间为0,需要扩容
			//_start = new T(x);
			_start = DataAllocator::Allocate();//
			Construct(_start,x);
			//new(_start)ValueType(x);
			_end = _start + 1;
			_endOfStorage = _end;
		}
		else if (pos == End() && _end < _endOfStorage){//2、尾插且不需要扩容
			_start[oldsize] = x;
			++_end;
		}
		else{
			//3、非尾插
			_CheckEndOfStorage();
			Iterator tmp = _end;
			pos = _start + n;//**************** very importent  有可能扩容,pos就不是要插入的那个位置了
			while (pos <= tmp){
				*(tmp + 1) = *tmp;
				--tmp;
			}
			*pos = x;
			++_end;
		}
		return _start+n;
	}
	//Iterator Erase(Iterator first,Iterator last);
	Iterator Erase(Iterator pos)
	{
		assert(pos != End());

		size_t size = Size();
		if (size == 0){
			return pos;
		}

		size_t n = pos - _start;
		Iterator tmp = pos;
		while (tmp < End()-1){
			*tmp = *(tmp + 1);
			tmp++;
		}
		_end--;
		*_end = ValueType();
		return _start + n;
	}
	bool Empty()
	{
		return Begin()==End();
	}
	size_t Size()
	{
		return _end - _start;
	}
	Reference operator[](size_t index)
	{
		assert(index >= 0 && index < Size());
		return *(Begin() + index);
	}
	ConstReference operator[](size_t index)const
	{
		assert(index >= 0 && index < Size());
		return *(Begin() + index);
	}
	//void resize(size_type sz, T c = T());
	//void reserve(size_type n);
	//Reference At(const size_t i);
	//void Swap(Self& x);
	//void Clear();

private:
	void _CheckEndOfStorage()
	{
		int oldcapacity = Size();
		if (_start != NULL && _end < _endOfStorage){
			return;
		}
		int newcapacity = oldcapacity * 2 ;
		
		/*//1.
		T* tmp = new T[newcapacity];
		int index = 0;
		while (index < oldcapacity){
			tmp[index] = _start[index];
			index++;
		}
		if (oldcapacity == 1)
			delete _start;
		else
			delete[] _start;//如果只有一个空间用delete _start;
		_start = tmp;
		_end = _start + oldcapacity;
		_endOfStorage = _start + newcapacity;*/
	    
		/*//2.
		T* tmp = DataAllocator::Allocate(newcapacity);

		int index = 0;
		while (index < oldcapacity){
			tmp[index] = _start[index];
			index++;
		}
		index = 0;
		while (index < oldcapacity){
			(&_start[index])->~T();
			index++;
		}
		DataAllocator::Deallocate(&_start[index], oldcapacity);
		_start = tmp;
		_end = _start + oldcapacity;
		_endOfStorage = _start + newcapacity;*/

		//3.
		T* tmp = DataAllocator::Allocate(newcapacity);
		UninitializedCopy(_start, _end, tmp);

		Destroy(_start, _end);
		DataAllocator::Deallocate(_start, oldcapacity);

		_start = tmp;
		_end = _start + oldcapacity;
		_endOfStorage = _start + newcapacity; 
	}
};

Test.cpp

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

void printVector2(Vector<int> v)
{
	size_t size = v.Size();
	Vector<int>::Iterator it = v.Begin();
	while (it!=v.End()){
		std::cout << *it << std::endl;
		++it;
	}
}
void printvector1(std::vector<int> v)
{
	size_t size = v.size();
	std::vector<int>::iterator it = v.begin();
	while (it != v.end()){
		std::cout << *it << std::endl;
		++it;
	}
}

void TestVector()
{
	//std::vector<int> v1;
	//v1.push_back(2);
	//std::vector<int>::iterator item;
	//item=v1.Begin();
	////v1.erase(item);
	////v1.pop_back();
	//printvector1(v1);


	Vector<int> v2;
	v2.PushBack(2);
	Vector<int>::Iterator ite;
	ite = v2.Begin();
	v2.Erase(ite);
	printVector2(v2);

	v2.PopBack();
	v2.PushBack(1);
	v2.PushBack(2);
	v2.PushBack(3);
	v2.PushBack(4);
	v2.PopBack();
	std::cout<<v2[0]<<std::endl;
	printVector2(v2);
	//ite = v2.end();
	//v2.erase(ite);
	//printvector2(v2);
	/*ite = v2.Begin();
	v2.insert(ite,5);
	printvector2(v2);
	v2.erase(ite);
	ite = v2.Begin();
	printvector2(v2);*/
	/*ite = v2.end();
	v2.erase(ite);*/
	//printvector2(v2);
}

vector还有两个函数 reserve()和resize()

分别是改变capacity和改变size

vector 的reserve增加了vector的capacity,但是它的size没有改变!而resize改变了vector的capacity同时也增加了它的size!
原因如下:

    reserve是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素。加入新的元素时,要调用push_back()/insert()函数。


    resize是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。此时再调用push_back()函数,是加在这个新的空间后面的。


     两个函数的参数形式也有区别的,reserve函数之后一个参数,即需要预留的容器的空间;resize函数可以有两个参数,第一个参数是容器新的大小, 第二个参数是要加入容器中的新元素,如果这个参数被省略,那么就调用元素对象的默认构造函数。