1. 程式人生 > >【STL】 vector 模擬實現

【STL】 vector 模擬實現

    上一篇部落格說了一下list的使用,其實vector用法基本上和list是一樣的,所以此篇部落格就只模擬實現以下vector。vector你可以把它理解成一個順序表或者陣列。只是STL裡的vector是由三個迭代器來維護的:_start(資料存放開始的位置),_finish(資料存放結束位置的下一個),_endofstorage(容量的最後一個位置)。vector裡的迭代器其實就是個指標。來看看程式碼實現:

#include<iostream>
#include<vector>
using namespace std;

template<class T>
class MyVector
{
public:
	typedef T* Iterator;
	typedef const T* ConstIterator;

	MyVector(size_t n=3)      //建構函式,初始化給3個T型別容量
		:_start(new T[n]), _finish(_start), _end_of_storage(_start+n)
	{
	}
	MyVector(const MyVector<T>& v)   //拷貝構造
	{
		if (v._finish - v._start > _finish - _start)
		{
			delete[] _start;
			_start = new T[v._finish - v._start];
			_finish = _start;
		}
		for (Iterator tmp = v._start; tmp != v._finish; tmp++)
		{
			*(_finish) = *tmp;
			_finish++;
		}
		_end_of_storage = _finish;
	}
	void PushBack(const T& x)   //尾插,這裡注意,即使呼叫的insert裡檢查了容量,尾插函式仍需檢測
	{
		CheckCapacity();
		Insert(End(), x);
	}
	void PopBack()
	{
		Iterator pos = End();   //前置的--因為返回的是臨時變數的值,所以不能直接對End()函式進行--
		Erase(--pos);
	}

	void Insert(Iterator pos, const T& x)
	{
		CheckCapacity();
		for (Iterator tmp = End(); tmp != pos;tmp--)
		{
			*tmp = *(tmp - 1);
		}
		*pos = x;
		_finish++;
	}

	void Erase(Iterator pos)
	{
		Iterator end = End();
		for (Iterator tmp = pos; tmp != (--end); tmp++)
		{
			*tmp = *(tmp + 1);
		}
		_finish--;
	}

	size_t Size()
	{
		return _finish - _start;
	}
	/************迭代器部分***********/
	Iterator Begin()
	{
		return _start;
	}
	Iterator End()
	{
		return _finish;
	}
	/*Iterator operator++(int)
	{
		Iterator tmp = *this;
		tmp++;
		return tmp;
	}
	Iterator& operator++()
	{
		Iterator tmp = *this;
		tmp++;
		return *this;
	}
	Iterator operator--(int)
	{
		Iterator tmp = *this;
		tmp--;
		return tmp;
	}
	Iterator& operator--()
	{
		Iterator tmp = *this;
		tmp--;
		return *this;
	}
	*/
private:
	void CheckCapacity()
	{
		if (_finish == _end_of_storage)
		{
			Iterator new_start = new T[2 * Size()];   //一次擴容原來的兩倍
			Iterator new_finish = new_start;
			for (Iterator i = Begin(); i != End(); i++,new_finish++)
			{
				*new_finish = *i;
			}
			delete[] _start;
			_start = new_start;
			_finish = new_finish;
			_end_of_storage = _start + 2 * Size();
		}
	}
private:
	Iterator _start;
	Iterator _finish;
	Iterator _end_of_storage;
};


void TestVector()
{
	MyVector<int> v;
	v.PushBack(1);
	v.PushBack(2);
	v.PushBack(3);
	v.PushBack(4);
	MyVector<int>::Iterator it;
	for (it = v.Begin(); it != v.End(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
	v.PopBack();
	v.PopBack();
	for (it = v.Begin(); it != v.End(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
	MyVector<int> v1(v);
	for (it = v1.Begin(); it != v1.End(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

寫vector時,犯了好多愚蠢的錯誤:

1.因為pushpack()函式是呼叫Insert()函式實現的,而Insert()函式內部有檢測容量,所以剛開始Pushpack()就沒有檢測,程式崩潰了。因為在Insert裡擴容時,等於說重新開闢了一塊更大的記憶體,那你Pushback傳過來的End()位置將永遠也找不到,因為那塊記憶體已經被釋放了。

2.其實這裡的迭代器它就是一個指標,根本沒必要再對它的++,--,什麼的進行過載,我好像是陷入了list的迷陣中無法自拔-_-....

    為什麼會這麼凌亂呢,因為寫vector時,我邊看《老九門》邊敲程式碼。。。回頭再看看真是。。。所以,作為程式設計師,該敲程式碼時還是老老實實敲吧。。。

    我這裡在拷貝構造時,只開闢了有效值個數,考慮到實際中拷貝後應該不會再插入,所以這樣做也是一種省空間的做法。

    vector包含的函式當然不止這些,有興趣可以查閱STL庫看看。