C++模拟标准库容器vector

使用模板写出简易版的标准库容器vector。主要使用了allocator来进行分配内存。代码存在大量注释。故实现细节查看代码

///头文件Vec.h
#pragma once
#ifndef VEC_H
#define VEC_H
#include <initializer_list>
#include <allocators>
#include <memory>
#include <utility>
#include <algorithm>


template<typename _Ty>	class Vec;		//重载运算符需要使用到

template<typename _Ty> 
bool operator==(const Vec<_Ty>&, const Vec<_Ty>&);		//判等运算

template<typename _Ty>
bool operator!=(const Vec<_Ty> &lhs, const Vec<_Ty> &rhs);

///模板类Vec  存放多种类型.模拟标准库容器存放元素
template<typename _Ty>
class Vec
{
	friend bool operator==<_Ty>(const Vec<_Ty>&, const Vec<_Ty>&);
public:
	typedef _Ty*  iterator;					//使用类型别名.将指针设置为迭代器类型
	typedef const _Ty* const_iterator;		
	///Consturct function
	Vec() : element(nullptr), firstFree(nullptr), cap(nullptr) {}		//默认构造函数
	Vec(const Vec&);			//拷贝构造
	Vec(Vec&&) noexcept;		//移动构造
	Vec(const std::initializer_list<_Ty>& il);		//列表构造

	/// 重载运算符
	Vec& operator=(const Vec&);		//拷贝赋值
	Vec& operator=(Vec&&) noexcept;	//移动赋值		
	_Ty& operator[](size_t n);		//下标运算符

	///成员函数
	void push_back(const _Ty& val);		//拷贝插入元素
	void push_back(_Ty&& val);			//移动插入元素
	void pop_back();		//弹出元素
	
	_Ty& front() const { return *element; }			//返回首元素
	_Ty& back() const { return *(firstFree - 1); }	//返回尾元素


	size_t size() const { return firstFree - element; }		//返回元素数量
	size_t capacity() const { return cap - element; }		//返回容器分配大小
	void resize(size_t n);		//重新分配内存大小

	template <typename...Args>
	void emplace_back(Args&&... args);		//模板函数。在尾部构造一个元素

	bool empty() const { return element == firstFree; }		//检查是否为空

	iterator begin() { return element; }			//返回首元素
	const_iterator cbegin() const { return element; }
	iterator end() { return firstFree; }
	const_iterator cend() const { return firstFree; } //返回尾后元素

	~Vec() { free(); }		//析构函数

private:
	static std::allocator<_Ty> alloc;			//负责分配内存
	//类成员
	_Ty *element;			//首元素
	_Ty *firstFree;			//第一个被释放的元素
	_Ty *cap;			//容器分配内存大小
	
	///工具函数
	void reallocator();		//重新分配内存。 无参数版
	void reallocator(size_t n);		//按照指定参数重新分配内存
	std::pair<iterator, iterator> allocCopy(const_iterator , const_iterator);		//拷贝指定范围内的元素
	void check() { if (size() == capacity()) reallocator(); }		//检查当前容量是否能够存放元素
	void free();		//释放内存操作
};

template<typename _Ty>
std::allocator<_Ty> Vec<_Ty>::alloc;

template<typename _Ty>
inline Vec<_Ty>::Vec(const Vec &vec)			//拷贝构造
{
	std::pair<iterator, iterator> data = allocCopy(vec.cbegin(), vec.cend());		//通过传递的参数构造内存

	element = data.first;
	cap = firstFree = data.second;		
}

template<typename _Ty>
inline Vec<_Ty>::Vec(Vec &&rhs) noexcept : element(rhs.element),firstFree(rhs.firstFree),cap(rhs.cap)
{
	rhs.element = rhs.firstFree = rhs.cap = nullptr;		//使其进行析构函数是安全的
}

template<typename _Ty>
inline Vec<_Ty>::Vec(const std::initializer_list<_Ty>& il)
{
	std::pair<iterator, iterator> data = allocCopy(il.begin(), il.end());		//拷贝构造元素内存

	element = data.first;
	cap = firstFree = data.second;
}

template<typename _Ty>
inline Vec<_Ty> & Vec<_Ty>::operator=(const Vec &rhs)
{
	std::pair<iterator, iterator> data = allocCopy(rhs.cbegin(), rhs.cend());		//先进行拷贝,即使自赋值也没关系

	free();		//释放原先内存

	///更新指针
	element = data.first;
	firstFree = cap = data.second;

	return *this;
}

template<typename _Ty>
inline Vec<_Ty> & Vec<_Ty>::operator=(Vec &&rhs) noexcept
{
	if (this != &rhs)		//检查自赋值
	{
		free();		//释放原先内存
		element = rhs.element;
		firstFree = rhs.firstFree;		
		cap = rhs.cap;

		rhs.element = rhs.firstFree = rhs.cap = nullptr;		//使其进行析构是安全的
	}
	return *this;
}

template<typename _Ty>
inline _Ty & Vec<_Ty>::operator[](size_t n)
{
	return *(element + n);		//返回首地址向前n的地址的元素
}

template<typename _Ty>
inline void Vec<_Ty>::push_back(const _Ty & val)
{
	check();		//检查当前容量是否足够

	alloc.construct(firstFree++, val);		//构造一个新值放入
}

template<typename _Ty>
inline void Vec<_Ty>::push_back(_Ty && val)
{
	check();		//检查内存是否足够

	alloc.construct(firstFree++, std::move(val));		//移动插入
}

template<typename _Ty>
inline void Vec<_Ty>::pop_back()
{
	alloc.destroy(--firstFree);		//每次销毁尾元素
}

template<typename _Ty>
inline void Vec<_Ty>::resize(size_t n)		//重新分配容器元素大小,如果要求数量小于当前size() 那么截去多余元素。 否则添加新元素进行默认初始化
{
	if (n < size())
	{
		for (size_t i = size(); i != n; --i)		//弹出末尾元素
			pop_back();
	}
	else if (n > size())
	{
		if (n > capacity())		//如果需要的大小大于当前容器容量的话,需要重新分配内存
			reallocator(n);	
		for (size_t i = size(); i != n; ++i)
			alloc.construct(firstFree++, _Ty());		//多余元素使用值初始化构造
	}
	///等于当前元素数量那么什么也不干
		
}
template<typename _Ty>
template<typename...Args>
inline
void Vec<_Ty>::emplace_back(Args&&... args)		//在尾部构造一个元素
{
	///转发参数包
	check();		//确保能够存放元素

	alloc.construct(firstFree++, std::forward<Args>(args)...);	//构造元素
}

template<typename _Ty>
inline void Vec<_Ty>::reallocator()		//当前容量不足的时候重新分配内存
{
	size_t newsize = size() ? size() * 2 : 2;		//当前容量是否为空,为空分配2个内存,否则分配之前的两倍内存
	
	reallocator(newsize);		
}

template<typename _Ty>
inline void Vec<_Ty>::reallocator(size_t n)
{
	///按照指定大小分配内存
	iterator first = alloc.allocate(n);		

	iterator last = std::uninitialized_copy(std::make_move_iterator(begin()),
										std::make_move_iterator(end()),
										first);		//	使用移动迭代器将元素移动到新内存中
	free();		//释放旧内存

	///更新指针
	element = first;
	firstFree = last;	
	cap = element + n;
}

template<typename _Ty>
inline std::pair<typename Vec<_Ty>::iterator, typename Vec<_Ty>::iterator>
Vec<_Ty>::allocCopy(const_iterator b, const_iterator e)
{
	///分配内存
	iterator data = alloc.allocate(e - b);

	return{ data,std::uninitialized_copy(b,e,data) };		//返回构造好的内存
}


template<typename _Ty>
inline void Vec<_Ty>::free()
{
	if (element)		//当之前分配了内存的时候才进行释放
	{
		for (iterator p = firstFree; p != element;)
			alloc.destroy(--p);						//销毁构造过的元素

		alloc.deallocate(element, capacity());		//释放内存当初分配内存的大小
	}
}

template<typename _Ty>
bool operator==(const Vec<_Ty> &lhs, const Vec<_Ty> &rhs)
{
	return std::equal(lhs.cbegin(), rhs.cend(), rhs.cbegin());
}

template<typename _Ty>
inline bool operator!=(const Vec<_Ty>& lhs, const Vec<_Ty>& rhs)
{
	return !(lhs == rhs);
}


#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

David_TD

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

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

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

打赏作者

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

抵扣说明:

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

余额充值