vector (仿sgi stl)

   // 參考侯捷大大的《STL源碼剖析》嘗試自己寫一個vector調高下代碼水平
  // VS2013下編譯 基本模仿sgi stl 
 // by : Ricardo
 
#include <iostream>
#include <memory> 
#include <iterator>
#include <algorithm>
using namespace std;

// 空間配置器默認用allocator<T>  sgi-STL裏面用的simple_alloc
template <typename T, typename Alloc = allocator<T> >
class vector
{
public:
	typedef T value_type; //STL標準要求
	typedef value_type* pointer; //STL標準要求
	typedef const value_type* const_pointer;
	 
	// vector內部維護的是一個連續線性空間 普通指針滿足所有條件 vector提供隨機迭代器
	typedef value_type* iterator; //STL標準要求 
	typedef const value_type* const_iterator;
	typedef value_type& reference; //STL標準要求
	typedef const value_type& const_reference;
	typedef size_t size_type;
	typedef ptrdiff_t difference_type; //STL標準要求

	// 下面兩個順序不能反 如果先typedef iterator版本的話話 reverse_iterator就不是模板了
	typedef reverse_iterator<const_iterator> const_reverse_iterator;  // 反向迭代器
	typedef reverse_iterator<iterator> reverse_iterator;
	
protected:
	// data_allocator 爲空間配置器 
	Alloc data_allocator;
	iterator start; // 目前使用空間的頭
	iterator finish; // 目前使用空間的尾
	iterator end_of_storage; // 目前可用空間的尾

protected:
	void insert_aux(iterator positiion, const T &x); // 提供插入操作

	template <typename InputIterator>
	void range_insert(iterator pos, InputIterator first, InputIterator last, input_iterator_tag);
	// 填充並且初始化
	void fill_initialize(size_type n, const T& value)
	{
		start = allocate_and_fill(n, value);
		finish = start + n;
		end_of_storage = finish;
	}
	// 分配空間,並且複製對象到分配的空間處
	iterator allocate_and_fill(size_type n, const T& x)
	{
		iterator result = data_allocator.allocate(n);
		uninitialized_fill_n(result, n, x);
		return result;
	}
	// 分配空間並copy一個區間的元素到新空間處
	template <typename ForwardIterator>
	iterator allocate_and_copy(size_type n, ForwardIterator first, ForwardIterator last)
	{
		iterator result = data_allocator.allocate(n);
		uninitialized_copy(first, last, result);
		return result;
	}
	// 將一個迭代器範圍插入到內存空間
	template <typename InputIterator>
	void range_initialize(InputIterator first, InputIterator last, input_iterator_tag)
	{
		for (; first != last; ++first)
		{
			push_back(*first);
		}
	}
	// 銷燬元素
	void destory(iterator first, iterator last)
	{
		for (; last != first; --last)
			data_allocator.destroy(--last);
	}
	// 釋放內存
	void deallocate()
	{			
		if (start)
			data_allocator.deallocate(start, end_of_storage - start);
		start = finish = end_of_storage = nullptr;
	}
public:
	//  獲取幾種迭代器
	iterator begin()
	{
		return start;
	}
	const_iterator begin() const
	{
		return start;
	}
	iterator end()
	{
		return finish;
	}
	const_iterator end() const
	{
		return finish;
	}
	reverse_iterator rbegin()
	{
		return reverse_iterator(end());
	}
	const_reverse_iterator rbegin() const
	{
		return const_reverse_iterator(end());
	}
	reverse_iterator rend()
	{
		return reverse_iterator(begin());
	}
	
	size_type size() const // 返回當前對象個數
	{
		return size_type(end() - begin());
	}
	size_type max_size() const // size_type是無符號數 -1溢出後爲size_t的最大值
	{
		return size_type(-1) / sizeof(T);
	}
	size_type capacity() const // 返回當前vector在重新進行內存分配以前所能容納的元素數量.
	{
		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);
	}

public:
	// 默認構造函數 不分配內存空間 成爲一個空容器
	vector() : start(nullptr), finish(nullptr), end_of_storage(nullptr){}
	// 比如vector<int> demo(4, value); 構造n個連續的value
	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);
	}
	// 比如vector<int> demo(4); 需要T提供默認構造函數
	explicit vector(size_type n) { fill_initialize(n, T()); }
	// copy構造函數
	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 <typename InputIterator>
	vector(InputIterator first, InputIterator last) : start(nullptr), finish(nullptr), end_of_storage(nullptr)
	{
		range_initialize(first, last, _Iter_cat(first)); // _Iter_cat是VS2013下的iterator_category()函數實現 決定某個迭代器的類型
	}
	// 析構函數
	~vector()
	{
		destory(start, finish); // 銷燬元素
		deallocate(); // 釋放內存
	}
	// 重載賦值運算符
	vector<T, Alloc>& operator=(const vector<T, Alloc>& x);

public:
	void reserve(size_type n) // 分配至少能容納n個元素的空間 不改變元素的數量 僅影響預先分配多大的內存
	{
		if (n > capacity())
		{
			const size_type old_size = size();
			iterator tmp = allocate_and_copy(n, start, finish);
			destory();
			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); }

	// 像vector尾部添加一個元素 如果有備用空間直接構造 如果木有則要重新分配內存
	void push_back(const T &x)
	{
		if (finish != end_of_storage)
		{
			data_allocator.construct(finish, x);
			++finish;
		}
		else
			insert_aux(end(), x);
	}
	// 刪除尾後元素 只析構 不釋放內存
	void pop_back()
	{
		--finish;
		data_allocator.destory(finish);
	}
	// 交換兩個vector 實際上是交換兩個容器內部指針	
	void swap(vector<T, Alloc> &x)
	{
		using std::swap;
		swap(start, x.start);
		swap(finish, x.finish);
		swap(end_of_storage, x.end_of_storage);
	}
	iterator erase(iterator position) // 刪除元素 不釋放內存
	{
		if ((position + 1) != end())
			copy(position+1, finish, position);
		--finsih;
		data_allocator.destory(finish);
		return position; // 返回值是指向刪除的最後一個元素的下一位置的迭代器
	}
	iterator erase(iterator first, iterator last) // 刪除一個範圍內的元素
	{
		iterator i = copy(last, finish, first);
		destory(i, finish);
		finish = finish - (last - first);
		return first; // 返回值是指向刪除的最後一個元素的下一位置的迭代器
	}
	void clear() // 清空容器
	{
		erase(begin(), end());
	}
	void resize(size_type new_size, const T& x) // 調整size但不會重新調整內存
	{
		if (new_size < size())
			erase(begin() + new_size, end());
		else
			insert(end(), new_size - size(), x);
	}

	iterator insert(iterator position, const T& x) // 在指定位置插入元素 返回指向新插入元素的迭代器
	{
		size_type n = position - begin(); //記錄position的距離
		if (finish != end_of_storage && position == end()) // 有備用空間並且在尾後插入
		{
			data_allocator.construct(finish, x);
			++finish;
		}
		else // 木有備用空間或者在中間某個地方插入 調用insert_aux來插入
			insert_aux(position, x);
		return begin() + n;
	}
	iterator insert(iterator position) // 插入一個默認構造的東東
	{
		return insert(position, T());
	}
	// 在指定位置position 插入n個元素
	void insert(iterator position, size_type n, const T& x);
	// 插入一個區間
	/*template <typename InputIterator>
	iterator insert(iterator position, InputIterator first, InputIterator last)
	{
		range_insert(position, first, last, _Iter_cat(first));
	}*/
	void insert(iterator position, const_iterator first, const_iterator last);

};
// vector內部實現部分如下


// 比較兩個容器是否相等
template <typename T, typename 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 <typename T, typename Alloc>
inline bool operator<(const vector<T, Alloc>& x, const vector<T, Alloc>& y)
{
	return lexicographical_compare(x.begin(), x.end(), y.back(), y.end());
}
// 交換兩個vector
template <typename T, typename Alloc>
inline void swap(vector<T, Alloc>& x, vector<T, Alloc>& y)
{
	x.swap(y);
}
// 重載賦值運算符
template <typename T, typename Alloc>
vector<T, Alloc>& vector<T, Alloc>::operator=(const vector<T, Alloc>& x)
{
	if (&x != this)
	{
		if (x.size() > capacity()) // 容量不夠
		{
			iterator tmp = allocate_and_copy(x.end()-x.begin(), x.begin(), x.end());
			destory(start, finish);
			deallocate();
			start = tmp;
			end_of_storage = start + (x.end() - x.begin());
		}
		else if (size() >= x.size()) // 容量足夠
		{
			iterator i = copy(x.begin(), x.end(), begin());
			destory(i, finish);
		}
		else // 有備用空間且元素數少於x
		{
			copy(x.begin(), x.begin() + size(), start);
			uninitialized_copy(x.begin() + size(), x.end(), finish);
		}
	}

}

//在position處插入x 可被insert使用
template <typename T, typename Alloc>
void vector<T, Alloc>::insert_aux(iterator position, const T& x)
{
	if (finish != end_of_storage) // 有備用空間的時候 將position開始 整體後移一位
	{
		data_allocator.construct(finish, *(finish-1));
		++finish;
		T x_copy = x;
		copy_backward(position, finish - 2, finish - 1);
		*position = x_copy;
	}
	else // 備用空間木有了 要插入怎麼辦
	{
		const size_type old_size = size();
		const size_type len = old_size != 0 ? 2 * old_size : 1; // 如果原大小爲0 配置一個元素的空間 不爲0則配置原大小兩倍大小空間
		iterator new_start = data_allocator.allocate(len); // 分配內存 new_start爲實際位置
		iterator new_finish = new_start;
		
		new_finish = uninitialized_copy(start, position, new_start);// 把原來vector的position之前的內容copy到新vector
		data_allocator.construct(new_finish, x); 
		++new_finish;
		new_finish = uninitialized_copy(position, finish, new_finish); //安插點的原內容全部拷貝過來
		//析構並釋放原vector
		destory(start, finish);
		deallocate();
		// 調整迭代器 指向新vector
		start = new_start;
		finish = new_finish;
		end_of_storage = new_start + len;
	}
}

// 在position處插入n個x對象
template <typename T, typename Alloc>
void vector<T, Alloc>::insert(iterator position, size_type n, const T& x)
{
	if (n != 0) // n = 0 直接return
	{
		if (size_type(end_of_storage - finish) >= n) //備用空間 >= 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;
				copy_backward(position, old_finish - n, old_finish);
				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;
				fill(position, old_finish, x_copy);
			}
		}
		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;

			new_finish = uninitialized_copy(start, position, new_start);
			new_finish = uninitialized_fill_n(new_finish, n, x);
			new_finish = uninitialized_copy(position, finish, new_finish);

			// 銷燬並釋放原vector
			destory(begin(), end());
			deallocate();
			// 調整標記
			start = new_start;
			finish = new_finish;
			end_of_storage = new_start + len;
		}
	}
}
// 在指定位置插入指定區間的對象 
/*template <typename T, typename Alloc>
template <typename 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 <typename T, typename Alloc>
void vector<T, Alloc>::insert(iterator position, const_iterator first, const_iterator last)
{
	if (first != last)
	{
		size_type n = last - first;
		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 - elems_after;
				copy_backward(position, old_finish-n, old_finish);
				copy(first, last, position);
			}
			else
			{
				uninitialized_copy(first+elems_after, last, finish);
				finish += n - elems_after;
				uninitialized_copy(position, old_finish, finish);
				finish += elems_after;
				copy(first, first + elems_after, 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);
			new_finish = new_start;

			new_finish = uninitialized_copy(start, position, new_start);
			new_finish = uninitialized_copy(first, last, new_finish);
			new_finish = uninitialized_copy(position, finish, new_finish);

			destory(start, finish);
			deallocate();
			start = new_start;
			finish = new_finish;
			end_of_storage = new_start + len;
		}
	}
}

int main()
{
	vector<int> demo(10, 1);
	for (auto &a : demo)
	{
		cout << a << " ";
	}
	cout << endl;
	vector<int> _demo(20, 2);

	swap(demo, _demo);
	for (auto &a : demo)
	{
		cout << a << " ";
	}
	cout << endl;
	demo.push_back(5);
	for (auto &a : demo)
	{
		cout << a << " ";
	}
	cout << endl;
	demo.insert(demo.begin(), 5, 2);
	for (auto &a : demo)
	{
		cout << a << " ";
	}
	cout << endl;
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章