作者的话: 我怕我追不上那个被寄予厚望的自己,所以我想努力奔跑
MyVector 实现
C++为我们提供了许多封装好的模板类,这些类使我们能够进行各种各样的操作。我们不需要知道他的底层是如何实现的,但我们如果知道了呢,那肯定是一件非常棒的事。此文章以 vector模板类为例,实现他的底层。
首先我们需要知道 vector 有哪些必要的操作,及各种属性:
数据成员:
- 动态数组存储数组 指针操作
- 动态数组的元素个数
- 动态数组的最大长度 ( 预留的空间,以1.5 至 2倍扩容,详情点击 C++11 之 shrink_to_fit 内存管理)
成员方法:
- 构造函数 与 析构函数
- 迭代器
- 运算符重载
- MyVector只实现:assign、swap、reserve、resize、 clear、size、capacity、empty、at、front、back、push_back 、pop_back 。
MyVector 框架如下:
template <typename T>
class CMyVector
{
// 数据成员
public:
// 方法实现
}
我们各种方法的定义都在类里面声明。
首先我们需要定义数据成员:
// 默认为私有成员
T* pBuff; // 动态数组的首地址 用来保存数据
size_t nSize; // 动态数组的元素个数
size_t nCapacity; // 动态数组的最大长度
接下来我们来写MyVector 各种操作声明的步骤:
迭代器
public:
// C++ 11
using iterator = T*; // 迭代器
using const_iterator = const T*; // 常量迭代器
public:
iterator begin()
{
return pBuff; // 首地址
}
iterator end()
{
return pBuff + nSize; // 最后一个元素的下一个地址
}
const_iteratr begin()const // 不可修改 符合常量的特性
{
return pBuff;
}
const_iterator end()const
{
return pBuff + nSize;
}
这样我们就可以使用迭代器来进行操作。
MyVector 构造方法:
public:
// 转递一个参数时,需要关闭隐式转换
explicit CMyVector(int size = 0); // 构造一个容器,元素个数为 size
CMyVector(int size, const T& elem); // 构造一个容器,元素个数为 size的值为 elem (复制的不可修改,且避免开销)
CMyVector(CMyVector<T> const& that); // 复制构造 (转递进来的不可修改 用const 限定)
~CMyVector(); // 析构
运算符重载:
public:
// 赋值重载
CMyVector<T>& opeator=(CMyVector<T> const& that);
// == 重载
bool operator==(CMyVector<T> const& that)const;
// != 重载
bool operator!=(CMyVector<T> const& that)const;
逻辑重载运算符,此文章只列举 ==与 !=,还有 >、<、 >=、 <= 就不在此处实现了。
功能实现:
我们将功能分为两类:有参 、无参
有参:
void assign(int n, const T& elem); // 复制 n个 elem 赋值给 this (修改原来的数据)
void swap(CMyVector<T>& that); // 交换两个 CMyVector 的数据
// 友元不属于 在哪里定义都一样
friend void swap(CMYVector<T>& v1, CMyVector<T>& v2
{
v1.swap(v2);
}
void reserve(int n); // 扩充数组容量,不能改小
void resize(int n); // 改变元素个数,改大扩容,改小 nSize = n
void resize(int n, const T& elem); // 改变元素个数,多的值用 elem初始化
无参:
void clear(); // 释放内存
size_t size() const; // 返回元素个数
size_t capacity() const; // 返回数组容量
bool empty() const; // 判断容器是否为空
T& at(int index) const; // 返回下标index 越界抛出 out_of_range 异常
T& operator[](int index) const; // 返回下标index
T& front(); // 返回第一个元素 不检查是否存在
T& back(); // 返回最后一个元素 不检查是否存在
// 我们最重要的两个方法
void push_back(const T& elem); // 后入 (爆菊)
void pop_back(); // 后出 (拉臭臭)
到此,我们基本的功能已经声明好了。