vector的成员变量有三个,分别是三个类模板参数类型的指针_start,_finish,_endofstorage,它们分别指向vector数组的首个元素,结尾元素的下一个空间,空间末尾。
vector()
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{}
//使用迭代器完成构造函数,初始化对象
template
vector(InputIterator first, InputIterator last)
:_start(nullptr)
,_finish(nullptr)
,_endofstorage(nullptr)
{
while (first != last)
{
push_back(*first);
++first;
}
_endofstorage = _finish;
}
//拷贝构造函数
vector(const vector& v)
{
//创建新对象,然后交换对象内的值,就可以完成深拷贝操作,这是深拷贝的现代写法
vector tmp(v.begin(), v.end());
Swap(tmp);
}
//赋值重载函数
vector& operator=(vector v)
{
swap(v);
return *this;
}
改变当前vector对象空间容量的大小,如果需要改变的容量大小大于vector对象的实际容量,就重新申请空间,扩容,否则就不需要扩容。
无返回值
(1)判断需要扩容的容量n是否大于当前对象的实际容量
(2)记录vector上的元素个数,并且在堆上申请大小n为的空间
(3)如果_start指针为空,这直接将_start指针指向堆上申请的空间
(4)将对象中的数据拷贝到在堆上新开辟的空间上,并释放该数据指向的堆上的空间
(5)改变当前对象的实际容量值
//改变vector的容量大小
void reserve(size_t n)
{
if (n > capacity())
{
size_t num = size();
T* tmp = new T[n];
if (_start == nullptr)
{
_start = tmp;
_finish = _start + num;
_endofstorage = _start + n;
}
else
{
//memcpy(tmp, _start, sizeof(T) * size());对于自定义类型,这种写法会发生浅拷贝,导致析构的时候,发生了两次析构
//这种写法能有效避免自定义类型的浅拷贝问题
for (size_t i = 0; i < num; i++)
{
tmp[i] = _start[i];//对于自定义类型,这里会发生深拷贝
}
delete[] _start;
_start = tmp;
_finish = _start + num;
_endofstorage = _start + n;
}
}
}
改变当前vector对象的元素的实际个数以及改变容量大小,并且初始化
无返回值
(1)判断需要改变的容量n是否大于当前对象的实际个数
(2)如果n小于等于当前对象的实际个数,就将该对象的_finish指针指向vector空间中的第n个元素。
(3)如果n大于等于当前对象的实际个数并且大于当前对象的实际容量,就调用reserve函数扩容vector对象的实际容量到n
(4)将_finish指针指向的空间赋值为val,再将_finish向后移
//改变容量,还有初始化
void resize(size_t n, T& val = T())
{
if (n < size())
{
_finish = _start + n;
}
else
{
if (n > capacity())
{
reserve(n);
}
while (_finish != _start + n)
{
*(_finish) = val;
++_finish;
}
}
}
在vector数组中的任意位置插入单个元素
返回插入位置的迭代器
(1)判断_finish指针是否等于_endofstorage指针,即判断是否需要扩容
(2)如果需要扩容,先记录下插入位置的迭代器(指针)pos在vector数组中的相对位置,然后调用reserve函数扩容,扩容会产生新的vector数组,但是该数组中的数据没有改变,只是指向该数组的指针发生了变化,所以需要在新的vector数组中更新迭代器(指针)pos。
(3)声明一个迭代器(指针)end,它指向该vector对象的最后一个元素,然后从end开始到pos,将一个一个元素向后移一位
(4)迭代器(指针)pos指向的空间赋值为x,再将_finish向后移
(5)返回迭代器(指针)pos
iterator insert(iterator pos, const T& x)
{
assert(pos >= _start);
assert(pos <= _finish);
if (_finish == _endofstorage)
{
//扩容可能会导致pos失效,所以需要在扩容之前记录pos的位置,扩容后更新一下pos
int len = pos - _start;
reverve(capacity() == 0 ? 4 : 2 * capacity());
iterator pos = _start + len;
}
iterator end = _finish - 1;
while (end >= pos)
{
*(end + 1) = *(end);
}
*(pos) = x;
_finish++;
return pos;
}
从vector数组中迭代器(指针)pos位置的值
返回删除后,删除位置的元素的指针
(1)声明一个迭代器it,它等于pos
(2)将it到_finish之间的元素全部向前移一位
(3)将_finish向前移一位,返回迭代器pos
//删除vector中的某一个元素
iterator erase(iterator pos)
{
assert(pos >= _start);
assert(pos < _finish);
iterator it = pos;
while (it < _finish - 1)
{
*(it) = *(it + 1);
++it;
}
_finish--;
//iterator begin = pos + 1;
//while (begin < _finish)
//{
// *(begin - 1) = *begin;
// ++begin;
//}
//--_finish;
return pos;
}
从vector数组中找到对应的元素
如果找到了就返回对应元素位置的迭代器,如果没找到就返回最后一个元素的下一个位置的迭代器。
(1)通过传过来的首元素的迭代器,和末尾元素的迭代器,遍历整个vector数组,
(2)解引用每个迭代器,然后和val作比较,如果相等,就会返回该迭代器
(3)如果没有一个匹配的迭代器,就返回最后一个元素的下一个位置的迭代器
//查找函数
template
InputIterator find(InputIterator first, InputIterator last, const T& val)
{
assert(first <= last);
while (first != last)
{
if (*first == val)
{
return first;
}
++first;
}
return last;
}