C++:vector的模拟实现

hello,各位小伙伴,本篇文章跟大家一起学习《C++:vector的模拟实现》,感谢大家对我上一篇的支持,如有什么问题,还请多多指教 !
如果本篇文章对你有帮助,还请各位点点赞!!!

话不多说,开始进入正题

文章目录

🍁全代码

cpp 复制代码
#pragma once
#include<iostream>
#include <assert.h>
#include <stdbool.h>

using namespace std;

namespace My_vector
{

	// 适配器 -- 复用
	template<class Iterator, class Ref, class Ptr>
	struct Reverse_iterator
	{
		Iterator _it;
		typedef Reverse_iterator<Iterator, Ref, Ptr> Self;

		Reverse_iterator(Iterator it)
			:_it(it)
		{}

		Ref operator*()
		{
			Iterator tmp = _it;
			return *(--tmp);
		}

		Ptr operator->()
		{
			return &(operator*());
		}

		Self& operator++()
		{
			--_it;
			return *this;
		}

		Self& operator--()
		{
			++_it;
			return *this;
		}

		bool operator!=(const Self& s)
		{
			return _it != s._it;
		}
	};

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

		typedef Reverse_iterator<iterator, T&, T*> reverse_iterator;
		typedef Reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;

		reverse_iterator rbegin()
		{
			return iterator(end());
		}

		reverse_iterator rend()
		{
			return iterator(begin());
		}

		const_reverse_iterator rbegin()
		{
			return const_iterator(end());
		}

		const_reverse_iterator rend()
		{
			return const_iterator(begin());
		}

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

		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endOfStorage, v._endOfStorage);
		}

		vector<T>& operator=(vector<T> v)//c = a;
		{					// 直接崩掉就是因为现代的赋值运算符重载是传值传参,会调用拷贝构造构造个临时变量,拷贝构造也需要初始化
			swap(v);
			return *this;
		}
		
		vector(const vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _endOfStorage(nullptr)
		{
			reserve(v.capacity());
			for (auto e : v)
			{
				push_back(e);
			}
		}

		template<class InPutIterator>
		vector(InPutIterator first, InPutIterator last)
		{
			while (first != last)
			{
				push_back((*first));
				++first;
			}
		}

		vector(initializer_list<T> a)
		{
			reserve(a.size());
			for (auto e : a)
			{
				push_back(e);
			}
		}
		

		vector(size_t n, const T& val = T())
		{
			reserve(n);
			for (int i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}

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

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

		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}

		const_iterator begin()const
		{
			return _start;
		}

		const_iterator end()const
		{
			return _finish;
		}

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

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

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t oldsize = size();
				T* tmp = new T[n];
				if (_start)
				{
					for (size_t i = 0; i < oldsize; ++i)
						tmp[i] = _start[i];

					// 3. 释放旧空间
					delete[] _start;
				}

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

		void resize(size_t n, const T& value = T())
		{
			if (n <= size())
			{
				_finish = _start + n;
				return;
			}

			if (n > capacity())
			{
				reserve(n);
			}
			iterator lt = _finish;
			_finish = _start + n;
			while (lt != _finish)
			{
				*lt = value;
				++lt;
			}
		}

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

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

		void push_back(const T& t)
		{
			/*if (_finish == _endOfStorage)
			{
				size_t newcapacity = (capacity() == 0) ? 4 : 2 * capacity();
				reserve(newcapacity);
			}
			*_finish = t;
			++_finish;*/

			insert(end(), t);
		}
		void popback()
		{
			assert(_start != _finish);
			--_finish;
		}

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

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

			--_finish;
		}

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

			// 空间不够先进行增容
			if (_finish == _endOfStorage)
			{
				//size_t size = size();
				size_t len = pos - _start;
				size_t newCapacity = (0 == capacity()) ? 4 : capacity() * 2;
				reserve(newCapacity);

				// 如果发生了增容,需要重置pos
				pos = _start + len;
			}

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

			return pos;
		}
		iterator insert(iterator pos,size_t n ,const T& t)
		{
			assert(pos >= _start);
			assert(pos <= _finish);

			// 空间不够先进行增容
			while (_finish + n >= _endOfStorage)
			{
				//size_t size = size();
				size_t len = pos - _start;
				size_t newCapacity = (0 == capacity()) ? 4 : capacity() * 2;
				reserve(newCapacity);

				// 如果发生了增容,需要重置pos
				pos = _start + len;
			}

			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + n) = *end;
				--end;
			}
			int cnt = 0;
			while (cnt < n)
			{
				*pos = t;
				++pos;
				++cnt;
			}
			_finish += n;

			return pos;
		}

	private:
		iterator _start;		// 指向数据块的开始
		iterator _finish;		// 指向有效数据的尾
		iterator _endOfStorage;  // 指向存储容量的尾
	};
}

🍁讲解

🍃一个类vector和一个结构体Reverse_iterator

vector里私有成员变量有:

cpp 复制代码
iterator _start;		// 指向数据块的开始
iterator _finish;		// 指向有效数据的尾
iterator _endOfStorage; // 指向所开空间的尾

结构体Reverse_iterator成员变量有:

cpp 复制代码
Iterator _it;// 迭代器,因为对于反向迭代器我们可以复用正向迭代器

🍃vector的迭代器

由于迭代器类似于指针,所以我们在这里用指针代替:

cpp 复制代码
// 正向迭代器
typedef T* iterator;
typedef const T* const_iterator;

// 反向迭代器
typedef Reverse_iterator<iterator, T&, T*> reverse_iterator;
typedef Reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;

🍃vector的成员函数

  • 1.默认构造函数:
cpp 复制代码
vector()
	:_start(nullptr)
	, _finish(nullptr)
	, _endOfStorage(nullptr)
{}
  • 2.传参构造函数

传元素个数和值(可不写,调用该类型的构造函数)

由于此原因,所以内置类型也就有了自己的默认构造函数

cpp 复制代码
vector(size_t n, const T& val = T())
{
	reserve(n);
	for (int i = 0; i < n; ++i)
	{
		push_back(val);// vector的尾插成员函数
	}
}

传迭代器区间

cpp 复制代码
template<class InPutIterator>
vector(InPutIterator first, InPutIterator last)
{
	while (first != last)
	{
		push_back((*first));
		++first;
	}
}

传初始化列表

cpp 复制代码
vector(initializer_list<T> a)
{
	reserve(a.size());
	for (auto e : a)
	{
		push_back(e);
	}
}
  • 3.拷贝构造函数
cpp 复制代码
vector(const vector<T>& v)
	:_start(nullptr)
	, _finish(nullptr)
	, _endOfStorage(nullptr)
{
	reserve(v.capacity());
	for (auto e : v)
	{
		push_back(e);
	}
}

🍃析构函数

cpp 复制代码
~vector()
{
	if (_start)
	{
		delete[] _start;
		_start = _finish = _endOfStorage = nullptr;
	}
}

🍃迭代器

cpp 复制代码
// 正向迭代器
iterator begin()
{
	return _start;
}

iterator end()
{
	return _finish;
}

const_iterator begin()const
{
	return _start;
}

const_iterator end()const
{
	return _finish;
}

// 反向迭代器
reverse_iterator rbegin()
{
	return iterator(end());// 复用正向迭代器
}

reverse_iterator rend()
{
	return iterator(begin());// 复用正向迭代器
}

const_reverse_iterator rbegin()
{
	return const_iterator(end());// 复用正向迭代器
}

const_reverse_iterator rend()
{
	return const_iterator(begin());// 复用正向迭代器
}

🍃交换函数

cpp 复制代码
void swap(vector<T>& v)
{
	std::swap(_start, v._start);
	std::swap(_finish, v._finish);
	std::swap(_endOfStorage, v._endOfStorage);
}

🍃赋值重载函数

cpp 复制代码
vector<T>& operator=(vector<T> v)//c = a;
{
	swap(v);// 复用交换函数
	return *this;
}

🍃vector相关的容器函数

  • 判断是否为空
cpp 复制代码
bool empty() const
{
	return _start == _finish;
}
  • 返回vrctor的大小
cpp 复制代码
size_t size()const
{
	return _finish - _start;
}
  • 返回该vector所开的空间
cpp 复制代码
size_t capacity()const
{
	return _endOfStorage - _start;
}

🍃reserve函数

预留空间,大大降低了数组需要被重新分配大小为了增加存储空间所用的时间,提高了效率

cpp 复制代码
void reserve(size_t n)
{
	if (n > capacity())
	{
		size_t oldsize = size();
		T* tmp = new T[n];
		if (_start)
		{
			for (size_t i = 0; i < oldsize; ++i)
				tmp[i] = _start[i];

			// 3. 释放旧空间
			delete[] _start;
		}

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

由于重新分配空间会导致指针_start,_finish,_endOfStorage失效,所以使用了oldsize记录_start和_finish的距离。

🍃resize函数

// 扩容时可以传第二个参数value来对后面的空间初始化

cpp 复制代码
void resize(size_t n, const T& value = T())
{
	// 缩容的情况
	if (n <= size())
	{
		_finish = _start + n;
		return;
	}
	
	// 扩容的情况
	if (n > capacity())
	{
		reserve(n);// 开空间
	}
	iterator lt = _finish;
	_finish = _start + n;
	while (lt != _finish)
	{
		*lt = value;
		++lt;
	}
}

🍃[]重载函数

cpp 复制代码
T& operator[](size_t i)
{
	assert(i < size());// 检查是否越界访问
	return _start[i];
}

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

🍃尾插函数和尾删函数

  • 尾插函数
cpp 复制代码
void push_back(const T& t)
{
	if (_finish == _endOfStorage)// 判断是否需要扩容
	{
		size_t newcapacity = (capacity() == 0) ? 4 : 2 * capacity();
		reserve(newcapacity);
	}
	*_finish = t;
	++_finish;

	// insert(end(), t);// 复用插入函数
}
  • 尾删函数
cpp 复制代码
void popback()
{
	assert(_start != _finish);
	--_finish;
}

🍃erase函数

  • 销毁函数
cpp 复制代码
void erase(iterator pos)
{
	assert(pos >= _start);// 判断是否越界
	assert(pos < _finish);// 判断是否越界

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

	--_finish;
}

🍃插入函数

  • 插入一个元素
cpp 复制代码
iterator insert(iterator pos, const T& t)
{
	assert(pos >= _start);
	assert(pos <= _finish);

	// 空间不够先进行增容
	if (_finish == _endOfStorage)
	{
		//size_t size = size();
		size_t len = pos - _start;
		size_t newCapacity = (0 == capacity()) ? 4 : capacity() * 2;
		reserve(newCapacity);

		// 如果发生了增容,需要重置pos,迭代器失效问题
		pos = _start + len;
	}

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

	return pos;
}
  • 插入多个元素
cpp 复制代码
iterator insert(iterator pos, size_t n, const T& t)
{
	assert(pos >= _start);
	assert(pos <= _finish);

	// 空间不够先进行增容
	while (_finish + n >= _endOfStorage)
	{
		//size_t size = size();
		size_t len = pos - _start;
		size_t newCapacity = (0 == capacity()) ? 4 : capacity() * 2;
		reserve(newCapacity);

		// 如果发生了增容,需要重置pos,迭代器失效问题
		pos = _start + len;
	}

	iterator end = _finish - 1;
	while (end >= pos)
	{
		*(end + n) = *end;
		--end;
	}
	int cnt = 0;
	while (cnt < n)
	{
		*pos = t;
		++pos;
		++cnt;
	}
	_finish += n;

	return pos;
}

🍁反向迭代器对正向迭代器的复用

这里3个模板参数,就是为了让编译器去判断该调用什么类型返回值的成员函数

cpp 复制代码
// 适配器 -- 复用
//             迭代器           引用        指针
template<class Iterator, class Ref, class Ptr>
struct Reverse_iterator
{
	Iterator _it;// 成员变量,正向迭代器
	typedef Reverse_iterator<Iterator, Ref, Ptr> Self;

	// 构造函数
	Reverse_iterator(Iterator it)
		:_it(it)
	{}

	Ref operator*()
	{
		Iterator tmp = _it;
		return *(--tmp);
	}

	Ptr operator->()
	{
		return &(operator*());
	}

	Self& operator++()
	{
		--_it;
		return *this;
	}

	Self& operator--()
	{
		++_it;
		return *this;
	}

	bool operator!=(const Self& s)
	{
		return _it != s._it;
	}
};

你学会了吗?

好啦,本章对于《C++:vector的模拟实现》的学习就先到这里,如果有什么问题,还请指教指教,希望本篇文章能够对你有所帮助,我们下一篇见!!!

如你喜欢,点点赞就是对我的支持,感谢感谢!!!

相关推荐
bryant_meng24 分钟前
【python】OpenCV—Image Moments
开发语言·python·opencv·moments·图片矩
若亦_Royi1 小时前
C++ 的大括号的用法合集
开发语言·c++
资源补给站2 小时前
大恒相机开发(2)—Python软触发调用采集图像
开发语言·python·数码相机
m0_748247552 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
6.942 小时前
Scala学习记录 递归调用 练习
开发语言·学习·scala
FF在路上3 小时前
Knife4j调试实体类传参扁平化模式修改:default-flat-param-object: true
java·开发语言
众拾达人3 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
皓木.3 小时前
Mybatis-Plus
java·开发语言
不良人天码星3 小时前
lombok插件不生效
java·开发语言·intellij-idea
源码哥_博纳软云4 小时前
JAVA同城服务场馆门店预约系统支持H5小程序APP源码
java·开发语言·微信小程序·小程序·微信公众平台