使用模板写出简易版的标准库容器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