天天看點

[C++STL]C++實作vector容器

代碼如下:

#pragma once
#include <iostream>
#include <assert.h>
using namespace std;

template<typename T>
class Vector
{
public:
	typedef T* iterator;
	typedef const T* const_iterator;

	Vector() :_start(nullptr), _finish(nullptr), _endOfStorage(nullptr) {};

	Vector(int n, const T &val = T()) :_start(new T[n]), _finish(_start + n), _endOfStorage(_finish)
	{
		for (int i = 0; i < n; i++)
		{
			_start[i] = val;
		}
	}



	/*使用新的疊代器的原因是使傳入的疊代器可以是任意類型的,
	如果使用Vector的疊代器,那麼傳入的疊代器的類型隻能和Vector的類型一樣,
	這裡拿string舉例,建立一個char類型的Vector,
	但是傳入的疊代器并不是char類型的,
	可以是字元數組的疊代器或者是string的疊代器。
	隻要通過解引用是char類型就可以
	例如:
	string str = "Hello Wecccccccc";
	Vector<char> v4(str.begin(), str.end());
	*/
	template<typename InputIterator>
	Vector(InputIterator first, InputIterator last) :_start(nullptr), _finish(nullptr), _endOfStorage(nullptr)
	{
		while (first != last)
		{
			push_back(*first);
			++first;
		}
	}

	~Vector()
	{
		if (_start)
		{
			delete[] _start;
			_start = _finish = _endOfStorage = nullptr;
		}
	}

	size_t size()const
	{
		return _finish - _start;
	}

	size_t capacity()const
	{
		return _endOfStorage - _start;
	}

	void push_back(const T&val)
	{
		if (_finish == _endOfStorage)
		{
			size_t newC = _endOfStorage == nullptr ? 1 : 2 * capacity();
			reserve(newC);
		}

		*_finish = val;
		++_finish;
	}

	//通過memcpy記憶體拷貝(淺拷貝),會造成二次釋放記憶體的情況,不安全,會報異常。
	/*void reserve(size_t n)
	{
		if (n > capacity())
		{
			size_t sz = size();
			T *tmp = new T[n];

			if (_start != nullptr)
			{
				memcpy(tmp, _start, sizeof(T) * size());
				delete[] _start;
			}

			_start = tmp;
			_finish = _start + sz;
			_endOfStorage = _start + n;
		}
	}*/

	//深拷貝
	void reserve(size_t n)
	{
		if (n > capacity())
		{
			size_t sz = size();
			T *tmp = new T[n];

			if (_start != nullptr)
			{
				for (size_t i = 0; i < sz; i++)
				{
					tmp[i] = _start[i];
				}
				delete[]_start;
			}

			_start = tmp;
			_finish = _start + sz;
			_endOfStorage = _start + n;
		}
	}

	iterator begin()
	{
		return _start;
	}

	iterator end()
	{
		return _finish;
	}

	const_iterator begin() const
	{
		return _start;
	}

	const_iterator end()const
	{
		return _finish;
	}


	T&operator[](size_t pos)
	{
		assert(pos < size());
		return _start[pos];
	}

	const T&operator[](size_t pos) const
	{
		assert(pos < size());
		return _start[pos];
	}

	void resize(size_t n, const T&val = T())
	{
		if (n > capacity())
		{
			reserve(n);
		}

		if (n > size())
		{
			while (_finish != _start + n)
			{
				*_finish = val;
				++_finish;
			}
		}

		_finish = _start + n;
	}

	void insert(iterator pos, const T &val)
	{
		assert(pos >= _start || pos < _finish);

		if (_finish == _endOfStorage)
		{
			size_t offset = pos - _start;
			size_t newC = _endOfStorage == nullptr ? 1 : 2 * capacity();
			reserve(newC);

			pos = _start + offset;
		}

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

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

		iterator start = pos + 1;

		while (start != _finish)
		{
			*(start - 1) = *start;
			++start;
		}
		--_finish;

		return pos + 1; //傳回值:指向删除元素的下一個元素。
	}

	void pop_back()
	{
		if (size() > 0) erase(end() - 1);
	}



private:
	iterator _start;
	iterator _finish;
	iterator _endOfStorage;
};

template<typename T>
void PrintVector(Vector<T> &vec)
{
	typename Vector<T>::iterator it = vec.begin();
	while (it != vec.end())
	{
		cout << *it;
		++it;
	}
	cout << endl;
}

template<typename T>
void PrintVectorFor(Vector<T> &vec)
{
	for (auto &e : vec)
	{
		cout << e;
	}
	cout << endl;
}
           

測試代碼如下:

#include <iostream>
#include <algorithm>
#include "Vector.h"
using namespace std;

int main()
{
	Vector<int>v1;
	Vector<int>v2(3,5);
	Vector<char>v3(5);
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
	cout << v2.size() << endl;
	cout << v2.capacity() << endl;
	cout << v3.size() << endl;
	cout << v3.capacity() << endl;
	string str = "Hello Wecccccccc";
	Vector<char> v4(str.begin(), str.end());
	v4.push_back('1');
	v4.push_back('2');
	v4.push_back('3');
	v4.reserve(100);
	cout << v4.size() << endl;
	cout << v4.capacity() << endl;
	PrintVector(v4);
	PrintVectorFor(v4);

	v4.resize(3);
	PrintVector(v4);
	v4.resize(4, '4');
	PrintVector(v4);

	Vector<int>v5;
	v5.push_back(2);
	v5.push_back(3);
	v5.push_back(5);
	v5.push_back(6);
	v5.insert(v5.begin(), 1);
	PrintVector(v5);
	v5.insert(v5.begin() + 3, 4);
	PrintVector(v5);
	v5.insert(v5.end(), 7);
	PrintVector(v5);
	v5.erase(v5.begin());
	PrintVector(v5);
	v5.erase(v5.end() - 1);
	PrintVector(v5);
	v5.pop_back();
	PrintVector(v5);
	Vector<int>::iterator it = find(v5.begin(), v5.end(), 5);
	if (it != v5.end())
	{
		cout << *it << endl;
	}
	else cout << "not find" << endl;

	it = find(v5.begin(), v5.end(), 1);
	if (it != v5.end())
	{
		cout << *it << endl;
	}
	else cout << "not find" << endl;
	return 0;
}
           

測試結果:

[C++STL]C++實作vector容器

繼續閱讀