1. vector 核心认识
- vector 是可变长数组,底层连续存储,支持随机访问。
- 维护三个指针:
_start:数据起始_finish:有效数据末尾_end_of_storage:容量末尾
- 扩容机制:VS (PJ) 约 1.5 倍 ,G++(SGI) 2 倍。
- 关键特性:支持随机访问、尾部增删 O (1)、中间增删 O (N)、迭代器可能失效。
2. 必须掌握的核心接口
2.1 构造函数
cpp
// 1. 无参构造
vector();
// 2. 构造 n 个 val
vector(size_t n, const T& val = T());
// 3. 拷贝构造(深拷贝)
vector(const vector& v);
// 4. 迭代器区间构造
template<class InputIterator>
vector(InputIterator first, InputIterator last);
2.2 容量与大小
cpp
size_t size() const; // 有效数据个数
size_t capacity() const; // 容量
bool empty() const; // 是否为空
void reserve(size_t n); // 只改容量,不初始化
void resize(size_t n, const T& val = T()); // 改size+初始化
2.3 增删改查
cpp
void push_back(const T& x); // 尾插
void pop_back(); // 尾删
iterator insert(iterator pos, const T& x); // 插入
iterator erase(iterator pos); // 删除
T& operator[](size_t i); // 随机访问
void swap(vector<T>& v); // 交换(O(1))
3. 迭代器失效
3.1 导致失效的操作
所有引起扩容 的操作:reserve/resize/insert/push_back底层空间被释放,原迭代器变成野指针。
3.2 erase 导致失效
删除后元素前移,被删位置迭代器失效。正确写法:
cpp
it = v.erase(it);
而非直接 erase(it) 后 ++it。
3.3 解决方法
使用前重新获取迭代器。
4. 深拷贝与 memcpy 陷阱
- vector 扩容必须深拷贝,逐个元素赋值。
- 禁止用 memcpy :memcpy 是浅拷贝,若元素是 string/vector 等带资源类型,会导致重复释放、崩溃。
5. vector 模拟实现(可直接运行)
5.1 成员变量
cpp
template<class T>
class vector
{
public:
typedef T* iterator;
typedef const T* const_iterator;
private:
iterator _start = nullptr;
iterator _finish = nullptr;
iterator _end_of_storage = nullptr;
};
5.2 构造 / 析构 / 拷贝 / 赋值
cpp
// 无参构造
vector() = default;
// n 个 val
vector(size_t n, const T& val = T())
{
reserve(n);
for (size_t i = 0; i < n; ++i)
_start[i] = val;
_finish = _start + n;
}
// 迭代器区间构造
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
while (first != last)
push_back(*first++);
}
// 拷贝构造(深拷贝)
vector(const vector<T>& v)
{
reserve(v.capacity());
for (size_t i = 0; i < v.size(); ++i)
_start[i] = v._start[i];
_finish = _start + v.size();
_end_of_storage = _start + v.capacity();
}
// 赋值重载(现代写法)
vector<T>& operator=(vector<T> v)
{
swap(v);
return *this;
}
// 析构
~vector()
{
delete[] _start;
_start = _finish = _end_of_storage = nullptr;
}
5.3 迭代器
cpp
iterator begin() { return _start; }
iterator end() { return _finish; }
const_iterator begin() const { return _start; }
const_iterator end() const { return _finish; }
5.4 容量 / 大小 / 访问
cpp
size_t size() const { return _finish - _start; }
size_t capacity() const { return _end_of_storage - _start; }
bool empty() const { return size() == 0; }
T& operator[](size_t i) { return _start[i]; }
const T& operator[](size_t i) const { return _start[i]; }
5.5 reserve / resize
cpp
void reserve(size_t n)
{
if (n > capacity())
{
size_t oldSize = size();
T* tmp = new T[n];
for (size_t i = 0; i < oldSize; ++i)
tmp[i] = _start[i];
delete[] _start;
_start = tmp;
_finish = _start + oldSize;
_end_of_storage = _start + n;
}
}
void resize(size_t n, const T& val = T())
{
size_t oldSize = size();
if (n > oldSize)
{
reserve(n);
for (size_t i = oldSize; i < n; ++i)
_start[i] = val;
}
_finish = _start + n;
}
5.6 增删
cpp
void push_back(const T& x)
{
if (_finish == _end_of_storage)
reserve(capacity() == 0 ? 4 : capacity() * 2);
*_finish++ = x;
}
void pop_back()
{
assert(!empty());
--_finish;
}
iterator insert(iterator pos, const T& x)
{
size_t len = pos - _start;
if (_finish == _end_of_storage)
reserve(capacity() == 0 ? 4 : capacity() * 2);
pos = _start + len;
for (iterator it = _finish; it > pos; --it)
*it = *(it - 1);
*pos = x;
++_finish;
return pos;
}
iterator erase(iterator pos)
{
for (iterator it = pos; it < end() - 1; ++it)
*it = *(it + 1);
--_finish;
return pos;
}
void swap(vector<T>& v)
{
std::swap(_start, v._start);
std::swap(_finish, v._finish);
std::swap(_end_of_storage, v._end_of_storage);
}
6. 总结
- vector 是连续存储的动态数组。
- 扩容是开新空间→拷贝→释放旧空间,不是原地扩展。
- 迭代器失效是手写 vector 最常见 bug。
- 元素带资源时不能用 memcpy,必须深拷贝。
reserve只扩容量,resize改 size 并初始化。- 现代写法赋值运算符:传参拷贝 + swap,异常安全、极简。