vector本质上就是使用动态分配数组来储存元素。
如果使用数组,当新元素插入时,这个数组需要被重新分配大小,为了增加存储空间。需要开辟新空间,然后将数据转移到新数组空间中。vector和数组空间分配策略不一样,vector会分配额外空间,分配空间比实际需要存储空间更大。
1.vector的构造函数

cpp
class vector
{
public:
vector()//默认构造不动
:_start(nullptr)
, _finish(nullptr)
{}
vector(vector<T>& v)//拷贝构造
{
reserve(v.capacity());//先扩容
for (const auto& e : v)
{
push_back(e);
}
}
vector(iterator first, iterator last)//迭代构造
{
while (first != last)
{
push_back(*first);
++first;
}
}
vector(size_t n, const T& x = T())
{
resize(n, x);
}
};
2.iterator使用
- begin/end 获取第一个数据位置的iterator/获取最后一个数据的下一个位置的iterator
- 获取最后一个数据元素的reverse_iterator,获取第一个数据前一个位置的reverse_iterator

cpp
class vector
{
public:
iterator begin()
{
return _start;
}
iterator end()
{
return _finish;
}
private:
iterator _start;//指向第一个元素
iterator _finish;//指向最后一个元素的后一个
iterator _end_storage;
};
3.vector空间增长机制
- capacity在vs下是按照1.5被扩容的,g++下是按2被扩容的。(vs是pj版本的STL,g++是SGI版本STL)
- reverse只负责开辟空间,如果提前知道使用多少空间,就可以避免vector增容的代价缺陷问题。
reserve(size_type n)只分配内存,不创建元素
cpp
std::vector<int> vec; vec.reserve(100); // 只分配内存,size() 不变
作用:预先分配至少能容纳 n 个元素的内存空间
size():保持不变(仍为 0)
capacity():增加(≥ n)
元素:不创建新元素,不改变现有元素
性能:避免多次重新分配,提高 push_back 效率
场景:知道大致元素数量时,避免重复分配
cppvoid reserve(size_t n) { if (capacity() < n)//需要扩容 { size_t oldsize = size(); //开空间 T* tmp = new T[n]; if (_start) { memcpy(tmp, _start, oldsize * sizeof(T));//拷贝 delete [] _start; } _start = tmp; _finish = _start + oldsize; _end_storage = _start + n; } }
resize(size_type n)改变容器大小,创建/销毁元素
cpp
std::vector<int> vec; vec.resize(100); // 创建100个元素,size变为100
作用:改变 vector 的大小,使其包含 n 个元素
size():变为 n
capacity():可能增加(如果 n > capacity)
元素:
如果 n > 当前 size:添加新元素(默认构造或指定值)
如果 n < 当前 size:删除尾部元素
场景:需要立即使用索引访问元素时
cpp//如果 n 大于当前容器大小,则通过在末尾插入足够多的元素来扩展内容,达到 n 的大小。 void resize(size_t n, const T& x = T())//默认构造 { size_t old = size(); if (n > old) { reserve(n);//先扩容,再插入 for (int i = 0; i < n - old; i++) { push_back(x); } } else { _finish = _start + n; } }
4.vector增删改查
push_back尾插
如果size超过capacity,需要扩容

cpp
void push_back(const T& x)
{
if (_finish == _end_storage)//一下扩两倍
{
size_t newcap = capacity() > 4 ? capacity() * 2 : 4;
reserve(newcap);
}
*_finish = x;
_finish++;
}
pop_back尾删

cpp
void pop_back()
{
assert(size() > 0);
--_finish;
}
insert插入

要小心扩容之后的pos不是本对象的迭代器了,需要重新计算返回
cpp
iterator insert(iterator pos, const T& x)//返回迭代器
{
//确保插入位置合法
assert(pos >= _start && pos <= _finish);
//如果它满了,扩容
if (_finish == _end_storage)
{
size_t len = pos - _start;
size_t newcap = size() > 4 ? 2 * size() : 4;
reserve(newcap);
//注意要把pos也改变了
pos = len + _start;
}
//把pos后的元素向后移动
iterator end = _finish-1;//_finish指向末尾元素后一个
while (end >= pos)
{
*(end + 1) = *end;
--end;
}
//插入元素
*pos = x;
++_finish;
return pos;
}
erase删除

直接把pos后的元素向前移动一位
cpp
iterator erase(iterator pos)
{
assert(pos >= _start && pos < _finish);
iterator it = pos;
while (it <_finish-1)
{
*it = *(it + 1);
++it;
}
--_finish;
return pos;
}
operator[]

cpp
T& operator[](size_t pos)
{
assert(pos < size());
return *(_start + pos);
}
5.vector迭代器失效问题
迭代器实质上就是一个指针,或者是对指针做了封装,比如vetcor迭代器就是原生态指针T*。就是迭代器底层对应指针指向的空间被收回了,造成的结果就是程序奔溃。(也就是野指针)
- 会导致存储空间变化的操作,都可能使迭代器失效,eg:resize,reserve,insert,assign,push_back(erase vs下会强制缩容也会导致迭代器失效)
- 不应该使用erase删除后的原来迭代器
cpp
#include <iostream>
using namespace std;
#include <vector>
int main()
{
int a[] = { 1,2,3,4 };
vector<int> v(a, a + sizeof(a)/sizeof(int));
auto pos = find(v.begin(), v.end(),1);
auto it = v.erase(pos);//pos被删除
//cout << *pos << endl;//报错
cout << *it << endl;
return 0;
}

