Vector 简介
vector 是 STL 库中提供的类模板,用于存储元素对象的顺序表。它提供增删查改接口,支持通过下标在任意位置读写。更多接口及用法可参考 。
详细讲解了 C++ STL 中 vector 容器的底层原理与源码实现。内容涵盖 vector 的基本概念、成员变量设计、三种构造函数、拷贝构造、析构函数、迭代器管理、运算符重载(如 []、=)、以及空间管理(reserve、resize)和元素操作(insert、erase、push_back、pop_back)。通过手写实现,深入理解动态内存管理、模板编程及深/浅拷贝机制,帮助开发者掌握 vector 的核心逻辑。

vector 是 STL 库中提供的类模板,用于存储元素对象的顺序表。它提供增删查改接口,支持通过下标在任意位置读写。更多接口及用法可参考 。
注意:STL 库的实现方式与普通顺序表略有不同。主要成员变量包括指向有效元素起始位置的 _start、终止位置下一个的 _finish 以及空间终止位置的 _endofstorge 迭代器(指针类型)。初始化时直接赋予空指针默认值,避免多次显式初始化。

库中提供了多种构造函数,以下逐一实现。关于内存分配,标准库通常使用内存池优化,但此处直接使用 new 开辟空间以简化讲解。
由于成员变量已设默认值,实现简单,但必须显式编写以避免编译器生成默认构造函数冲突。

参数中给 T 类型默认值 T()。对于内置类型(如 int),C++ 会将其视为可调用默认构造的对象(如返回 0)。

使用函数模板支持不同类型的迭代器初始化。

返回 vector 中的元素个数。

返回 vector 中的空间大小。

不可使用 memcpy,因为若 T 为动态内存类型,需深拷贝。应逐个元素赋值,要求元素对象重载赋值运算符。

采用传参拷贝后交换的方式(Copy-and-Swap),确保异常安全并释放旧空间。

分别返回可读可写及只读迭代器,指向首元素及末尾元素下一个位置。

提供非 const 和 const 版本,支持下标访问。

涉及深拷贝交换,借用算法库中的 swap 函数。

开辟指定大小空间,若已有元素则拷贝。

开辟指定大小空间,用 val 初始化,缺省值为 T()。

在指定位置插入值,返回新位置迭代器。注意插入可能导致空间扩容,原迭代器失效。

尾部插入,复用 insert 实现。

删除指定位置元素,返回该位置迭代器。若删除最后一个,传入迭代器失效。

尾部删除,复用 erase 实现。

#include <iostream>
#include <cassert>
#include <algorithm>
using namespace std;
namespace bea {
template<class T>
class vector {
typedef T* iterator;
typedef const T* const_iterator;
public:
// 空构造
vector() {}
// 用 n 个元素对象进行初始化
vector(size_t n, const T& val = T()) {
_start = new T[n + 5];
for (size_t i = 0; i < n; i++) {
_start[i] = val;
}
_finish = _start + n;
_endofstorge = _start + n + 4;
}
// 使用一个迭代器区间进行初始化
template<class InputIterator>
vector(InputIterator first, InputIterator last) {
size_t n = last - first;
_start = new T[n + 5];
InputIterator it1 = first, it2 = _start;
while (it1 < last) {
*it2 = *it1;
it1++, it2++;
}
_finish = _start + n;
_endofstorge = _start + n + 4;
}
// 拷贝构造函数
vector(const vector& x) {
size_t sz = x.size();
_start = new T[sz + 5];
for (size_t i = 0; i < sz; i++) {
_start[i] = x._start[i];
}
_finish = _start + sz;
_endofstorge = _start + sz + 4;
}
// size 函数
size_t size() const {
return _finish - _start;
}
// capacity 函数
size_t capacity() const {
return _endofstorge - _start + 1;
}
// begin 函数
iterator begin() { return _start; }
const_iterator begin() const { return _start; }
// end 函数
iterator end() { return _finish; }
const_iterator end() const { return _finish; }
// [] 操作符重载
T& operator[](size_t pos) {
assert(pos < size());
return _start[pos];
}
const T& operator[](size_t pos) const {
assert(pos < size());
return _start[pos];
}
// 交换函数
void swap(vector& x) {
std::swap(x._start, _start);
std::swap(x._finish, _finish);
std::swap(x._endofstorge, _endofstorge);
}
// 赋值运算符重载
vector& operator=(const vector x) {
swap(x);
return *this;
}
// 开空间相关函数
void reserve(size_t n) {
size_t sz = size();
if (n <= size()) return;
iterator tmp = new T[n + 5];
if (_start) {
for (size_t i = 0; i < sz; i++) {
tmp[i] = _start[i];
}
delete[] _start;
}
_finish = tmp + sz;
_start = tmp;
_endofstorge = tmp + n + 4;
}
// insert 函数
iterator insert(iterator pos, const T& val) {
assert(pos <= _finish);
int n = pos - _start;
if (capacity() < size() + 1) {
reserve(size() + 5);
}
pos = _start + n;
iterator end = _finish - 1, next = _finish;
while (next > pos) {
*next = *end;
end--, next--;
}
*pos = val;
_finish++;
return pos;
}
void push_back(const T& val) {
insert(_finish, val);
}
void resize(size_t n, T& val = T()) {
vector(n, val);
}
// erase 函数
iterator erase(iterator pos) {
assert(pos < _finish);
iterator end = pos + 1, front = pos;
while (end < _finish) {
*front = *end;
front++, end++;
}
_finish--;
if (pos == _finish) return nullptr;
else return pos;
}
// pop_back 函数
void pop_back() {
erase(_finish - 1);
}
// 析构函数
~vector() {
delete[] _start;
_start = nullptr;
_finish = nullptr;
_endofstorge = nullptr;
}
private:
iterator _start = nullptr;
iterator _finish = nullptr;
iterator _endofstorge = nullptr;
};
}

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online