STL之Vector的模拟实现

STL之vector的模拟实现

    • 一、vector深度剖析以及模拟实现
    • 注意:
  • 二、使用memcpy拷贝问题

一、vector深度剖析以及模拟实现

STL之Vector的模拟实现_第1张图片

#include
#include
#include
#include
#include
using namespace std;
namespace vr
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		vector()
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{}
		~vector()
		{
			if (_start)
			{
				delete[] _start;
			}
			_start = _finish = _endofstorage = nullptr;
		}
		vector(const vector<T>& v)
			:_start(nullptr)
			,_finish(nullptr)
			,_endofstorage(nullptr)
		{
			reserve(v.capacity());
			for (auto e : v)
			{
				push_back(e);
			}
		}
		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);
		}
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _end;
		}
		const_iterator begin() const
		{
			return _start;
		}
		const_iterator end() const
		{
			return _end;
		}
		size_t capacity()
		{
			return _endofstorage - _start;
		}
		size_t size()
		{
			return _finish - _start;
		}
		bool empty() const
		{
			return _start == _finish;
		}
		T& operator[](size_t i)
		{
			return _start[i];
		}
		//传统写法
		//vector& operator=(const vector& v)
		//{
		//	if (this != &v)
		//	{
		//		delete[] _start;//释放旧空间
		//		_start = new T[v.capacity()];//开辟新空间
		//		memcpy(_start, v._start, sizeof(T) * v.size());
		//		_finish = _start + v.size();
		//		_endofstorage = _start + v.capacity();
		//		_start = new T[];
		//	}
		//}
		//现代写法
		vector<T>& operator=(const vector<T>& v)
		{
			swap(v);
			return *this;
		}
		const T& operator[](size_t i)
		{
			return _start[i];
		}
		void resize(size_t n, T val = T())
		{
			if (n < size())
			{
				_finish = _start + n;
			}
			else
			{
				if (n < capacity())
				{
					while (_finish < _start + n)
					{
						*_finish = val;
						++_finish;
					}
				}
				else
				{
					reserve(n);
					while (_finish < _start + n)
					{
						*_finish = val;
						++_finish;
					}
				}

			}
		}
		void reserve(size_t n)
		{
			if (n > capacity)
			{
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)//判断旧空间是否为空
				{
					memcpy(tmp, _start, sz*sizeof(T));
					delete[] _start;
				}
				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}

		void push_back(const T& x)
		{
			if (_finish == _endofstorage)
			{
				size_t nwcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapcity);
			}
			*finish = x;
			++_finish;
		}
		void pop_back()
		{
			assert(!empty());
			--_finsh;
		}
		void insert(iterator pos, const T& x)
		{
			if (_finish==_endofstorage)
			{
				size_t len = pos - _start;
				size_t nwcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapcity);
				//更新pos,解决增容后Pos失效的问题
				pos = len + _start;
			}
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;
			++_finish;
		}
		iterator erase(iterator pos)
		{
			iterator it = pos + 1;
			while (it != finish)
			{
				*(it - 1) = *it;
				++it;
			}
			--_finish;
			return pos;
		}
	private:
		iterator _start;//指向这个数组第一个位置的指针
		iterator _finish;//指向最后一个数据下一个位置的指针
		iterator _endofstorage;//指向容量空间最后一个空间下一个位置
	};

注意:

1.const修饰的变量只能调取const修饰的函数。
2.reserve开辟容量空间时开辟的新空间不能使用memcpy把旧空间的数据拷贝过去,要使用循环赋值过去。因为memcpy是浅拷贝,memcpy函数reserve出来的容器与原容器指向同一个字符串空间,当原容器在释放字符时会调用析构函数,导致新容器指向的是不存在的空间,导致程序崩溃。

二、使用memcpy拷贝问题

问题分析:
1.memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中。
2.如果拷贝的是内置类型的元素,memcpy即高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。
STL之Vector的模拟实现_第2张图片
结论:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。

你可能感兴趣的:(c++,c++,算法,ubuntu)