一. 定义和成员变量
为了避免和标准库中的命名冲突, 在自己的命名空间中定义Vector.
私有成员也只需要三个指针: _start(起始位置), _finish(结束位置), _end_of_storage.
所以像 size(), capacity() 的函数直接使用指针相减即可.
namespace My_Vector
{
template<class T>
class vector
{
public:
// Vector的迭代器也是一个原生指针
typedef T* iterator;
typedef const T* const_iterator;
size_t size() const
{
return _finish - _start;
}
size_t capacity() const
{
return _end_of_storage - _start;
}
private:
iterator _start = nullptr; // 指向有效数据的开始
iterator _finish = nullptr; // 指向有效数据的尾
iterator _end_of_storage = nullptr; // 指向存储容量的尾
};
}
二. 迭代器
Vector 的迭代器是一个原生指针, 直接返回指针即可.
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
const_iterator begin() const
{
return _start;
}
const_iterator end() const
{
return _finish;
}
三. 默认成员函数
1. 构造函数
Vector 的无参构造函数这里在成员变量声明时给了缺省值, 所以不需要任何处理.
迭代器区间初始化直接将区间中的每个对象插入即可.
//无参构造函数
vector()
{}
//迭代器区间初始化
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
int sz = last - first; //区间大小
reserve(sz); //reserve() 开辟空间
while (first != last) //插入数据
{
push_back(*first);
++first;
}
}
2. 析构函数
直接释放空间, 置空指针即可.
~vector()
{
delete[] _start; //这里在 reserve() 中 new[] 开辟的空间, 所以 delete[] 释放
_start = _finish = _end_of_storage = nullptr;
}
3. 拷贝构造
可以先开辟空间, 然后使用迭代器将每个对象插入; 也可以直接使用迭代器区间初始化.
vector(const vector<T>& v)
{
/*
reserve(v.capacity()); //reserve() 开辟空间
for (const auto& e : v) //插入数据
push_back(e);
*/
vector<T> tmp(v.begin(), v.end()); //使用迭代器区间初始化 临时对象 tmp
swap(tmp); //交换 tmp 对象和 this 对象的成员变量 的指针
}
4. 赋值重载
利用拷贝构造实现即可.
vector<T>& operator= (vector<T> v) //使用拷贝构造初始化 临时对象 v
{
swap(v); //交换 v 临时对象和 *this 对象的成员变量
return *this;
}
四. 其他成员函数
1. Vector 内置 swap
直接交换成员变量即可.
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_end_of_storage, v._end_of_storage);
}
2. operator[ ]
返回 解引用指针后的引用即可.
T& operator[](size_t pos)
{
return *(_start + pos);
}
const T& operator[](size_t pos) const
{
return *(_start + pos);
}
3. reserve()
若扩容后需要挪动数据, 由于 Vector 需要适应各种类型, 所以 T 可以是任何类型, 所以挪动数据时如果是自定义类型必须使用 = (赋值重载) 进行深拷贝(内置类型使用 = 无所谓).
void reserve(size_t n)
{
if (n > capacity()) //检查是否需要扩容
{
size_t old_sz = size(); //保存旧数据的大小
T* new_start = new T[n]; //开辟新空间
if (_start)
{
for (size_t i = 0; i < old_sz; i++) //插入数据
*(new_start + i) = *(_start + i); //深拷贝
delete[] _start; //释放旧空间
}
_start = new_start; //更新成员变量
_finish = _start + old_sz;
_end_of_storage = _start + n;
}
}
4. resize()
void resize(size_t n, const T& value = T())
{
if (n > size()) //检查是否需要插入数据
{
reserve(n); //这里没有判断是否需要扩容, reserve() 函数中会判断
for (int i = size(); i < n; i++) //插入数据
push_back(value);
}
else
_finish = _start + n; //若不需要插入数据, 直接更改结束位置即可
}
5. insert()
iterator insert(iterator pos, const T& x)
{
assert(pos >= _start && pos <= _finish); //判断 pos 是否越界
if (_finish == _end_of_storage) //检查是否需要扩容
{
size_t sz = pos - _start; //记录 pos 的位置
reserve((capacity() == 0 ? 4 : capacity() * 2)); //reserve() 空间
pos = _start + sz; //更新 pos
}
iterator end = _finish;
while (end != pos) //挪动数据
{
*end = *(end - 1);
--end;
}
*pos = x; //插入 x
++_finish; //更新结束位置
return pos;
}
6. erase()
iterator erase(iterator pos)
{
assert(pos >= _start && pos < _finish); //判断 pos 是否越界
iterator it = pos+1;
while (it != _finish) //挪动数据
{
*(it-1) = *it;
++it;
}
--_finish; //更新结束位置
return pos;
}