C++ -- vector类模拟实现

文章详细介绍了如何在C++中模拟实现vector类,包括构造函数、析构函数、reserve方法、resize方法、insert方法、erase方法、push_back和pop_back方法,以及迭代器的操作。同时,文章讨论了模板使用、内存管理、迭代器失效等问题。
摘要由CSDN通过智能技术生成

C++ – vector类模拟实现

0. 成员变量

template<class T>
typedef T* iterator;
typedef const T* const_iterator;
iterator _start;
iterator _finish;
iterator _end_of_storage;
  1. 为什么这里需要模板呢?

因为我们使用数组可能是int、char等等类型,这里就依靠是顺序存储的特性,就直接用指针来充当成员变量。

1. 构造函数

vector()
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{}

vector(size_t n, const T& val = T()) //T()->T类型的构造 && const T&引用修饰->起别名延长了生命周期
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	reserve(n);
	for (size_t i = 0; i < n; ++i)
	{
		push_back(val);
	}
}

template <class InputIterator>
vector(InputIterator first, InputIterator last) //迭代器区间
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	while (first != last)
	{
		push_back(*first);
		++first;
	}
}
  1. 为什么这里的const T& val = T()?

这里的写法是为了给一个默认值,T()是针对自定义类型:string、vector等等。内置类型int()、char()等都是由编译器来初始化

2. 析构函数

~vector()
{
	delete[] _start;
	_start = _finish = _end_of_storage = nullptr;
}

3. reserve方法

void reserve(size_t capa)
{
	if (capa > capacity())
	{
		size_t len = size(); //OK:记录当前长度
		T* tmp = new T[capa];
		if (_start != nullptr)
		{
			for (size_t i = 0; i < len; ++i)
			{
				tmp[i] = _start[i];
			}
			delete[] _start;
		}
		_start = tmp;
		_finish = _start + len;
		_end_of_storage = _start + capa;
	}
}
  1. 操作:

    • 是否扩容
    • 拷贝数据
    • 变化成员变量
  2. 为什么_finish = _start + len,而不是 _finish = _start + size()?

因为size() = _finish - _start , _finish = _start + size() --> _finish = _start + _finiosh - _start

5. resize方法

void resize(size_t capa, T val = T())
{
	if (capa < size())
	{
		_finish = _start + capa;
	}
	else
	{
		if (capa > capacity())
		{
			reserve(capa);
		}
		while (_finish != _start + capa)
		{
			*_finish = val;
			++_finish;
		}
	}
}

6. insert方法

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

	if (_finish == _end_of_storage)
	{
		size_t len = pos - _start; //记录当前pos距离_start的距离
		reserve(capacity() == 0 ? 4 : capacity() * 2);
		pos = _start + len; //扩容:因为new的新空间会导致pos不在空间中导致后面while循环出错(pos失效解决方案)
	}

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

	return pos;
}
  1. 为什么需要接受pos呢?

扩容问题会导致new出新的空间给_start,连续插入会导致pos迭代器失效

  1. 对没有改动pos进行测试:
void test1()
{
	int arr[] = { 1,2,3,4};
	vector<int> v(arr, arr + sizeof(arr) / sizeof(int));
	v.insert(v.end(), 10);
	for (auto i : v)
	{
		cout << i << " ";
	}
	cout << endl;
}

reserve后pos不在[_start, _finish)范围内,解决方案就是改动pos

7. erase方法

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

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

	--_finish;

	return pos; //没有返回pos就导致迭代器失效
}

visual studio2019中的erase机制是一定是会pos迭代器失效。

8. push_back方法

void push_back(const T& val)
{
	if (_finish == _end_of_storage)
	{
		reserve(capacity() == 0 ? 4 : capacity() * 2);
	}
	*(_finish) = val;
	++_finish;
}

9. pop_back方法

void pop_back()
{
	assert(!empty());
	--_finish;
}

10. []运算符重载

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

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

11. 拷贝构造

vector(const vector<T>& v)
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	reserve(v.capacity());
	_start = new T[v.capacity()];
	for (size_t i = 0; i < v.size(); ++i)
	{
		_start[i] = v._start[i];
	}
	_finish = _start + v.size();
	_end_of_storage = _start + v.capacity();
}
  1. 为什么用for循环依次拷贝数据,而不是memcpy()呢?

假如是string类型,拷贝的时候就需要深拷贝,但是memcpy是浅拷贝

12. 迭代器

typedef T* iterator;
typedef const T* const_iterator;
iterator begin()
{
	return _start; //传值返回:临时对象具有常性
}
iterator end()
{
	return _finish;
}
const_iterator begin() const
{
	return _start;
}
const_iterator end() const
{
	return _finish;
}

13. 完整代码

#pragma once
#include <assert.h>

namespace myvector
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

		vector()
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{}

		vector(size_t n, const T& val = T()) //T()->T类型的构造 && const T&引用修饰->起别名延长了生命周期
			:_start(nullptr)
			,_finish(nullptr)
			,_end_of_storage(nullptr)
		{
			reserve(n);
			for (size_t i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}

		vector(int n, const T& val = T()) //T()->T类型的构造 && const T&引用修饰->起别名延长了生命周期
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(n);
			for (int i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}

		template <class InputIterator>
		vector(InputIterator first, InputIterator last)
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		/*vector(const vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(v.capacity());
			for (auto i : v)
			{
				push_back(i);
			}
		}*/

		//vector<自定义类型>-->两次析构会程序崩溃
		//vector(const vector<T>& v)
		//	:_start(nullptr)
		//	, _finish(nullptr)
		//	, _end_of_storage(nullptr)
		//{
		//	reserve(v.capacity());
		//	_start = new T[v.capacity()];
		//	memcpy(_start, v._start, sizeof(T) * v.size()); //memcpy也是浅拷贝
		//	_finish = _start + v.size();
		//	_end_of_storage = _start + v.capacity();
		//}

		vector(const vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(v.capacity());
			_start = new T[v.capacity()];
			for (size_t i = 0; i < v.size(); ++i)
			{
				_start[i] = v._start[i];
			}
			_finish = _start + v.size();
			_end_of_storage = _start + v.capacity();
		}

		iterator begin()
		{
			return _start; //传值返回:临时对象具有常性
		}

		iterator end()
		{
			return _finish;
		}

		const_iterator begin() const
		{
			return _start;
		}

		const_iterator end() const
		{
			return _finish;
		}

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

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

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

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

		void resize(size_t capa, T val = T())
		{
			if (capa < size())
			{
				_finish = _start + capa;
			}
			else
			{
				if (capa > capacity())
				{
					reserve(capa);
				}
				while (_finish != _start + capa)
				{
					*_finish = val;
					++_finish;
				}
			}
		}

		//void reserve(size_t capa)
		//{
		//	if (capa > capacity())
		//	{
		//		size_t len = size(); //OK:记录当前长度
		//		T* tmp = new T[capa];
		//		if (_start != nullptr)
		//		{
		//			memcpy(tmp, _start, sizeof(T) * size()); //memcpy是浅拷贝
		//			delete[] _start;
		//		}
		//		_start = tmp;
		//		_finish = _start + len;
		//		//_finish = _start + size(); //err:size() = _finish - _start --> _finish = _finish
		//		_end_of_storage = _start + capa;
		//	}
		//}

		void reserve(size_t capa)
		{
			if (capa > capacity())
			{
				size_t len = size(); //OK:记录当前长度
				T* tmp = new T[capa];
				if (_start != nullptr)
				{
					for (size_t i = 0; i < len; ++i)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}
				_start = tmp;
				_finish = _start + len;
				//_finish = _start + size(); //err:size() = _finish - _start --> _finish = _finish
				_end_of_storage = _start + capa;
			}
		}

		void push_back(const T& val)
		{
			if (_finish == _end_of_storage)
			{
				reserve(capacity() == 0 ? 4 : capacity() * 2);
			}
			*(_finish) = val;
			++_finish;
		}

		bool empty()
		{
			return _start == _finish;
		}

		void pop_back()
		{
			assert(!empty());
			--_finish;
		}

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

			if (_finish == _end_of_storage)
			{
				size_t len = pos - _start; //记录当前pos距离_start的距离
				reserve(capacity() == 0 ? 4 : capacity() * 2);
				pos = _start + len; //扩容:因为new的新空间会导致pos不在空间中导致后面while循环出错(pos失效解决方案)
			}

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

			return pos;
		}

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

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

			--_finish;

			return pos; //没有返回pos就导致迭代器失效
		}

		~vector()
		{
			delete[] _start;
			_start = _finish = _end_of_storage = nullptr;
		}

		void out(const vector<T>& v)
		{
			for (size_t i = 0; i < v.size(); ++i)
			{
				cout << v[i] << " ";
			}
			cout << endl;

			vector<T>::const_iterator it = v.begin();
			while (it != v.end())
			{
				cout << *it << " ";
				++it;
			}
			cout << endl;
		}

	private:
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;
	};
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

脚踏车(crush)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值