在 C++ 的 STL(标准模板库)中,vector 是最常用、最基础的序列式容器,本质是动态数组。它解决了传统静态数组长度固定、无法灵活扩容的痛点,支持随机访问、尾部高效增删元素,是开发中处理可变长度数组的首选工具。
本文从基础概念、核心操作、常用 API、底层原理、使用场景五个维度,整理 vector 的核心知识点,适合学习和复习使用。
一、vector 基础认知
示例:
表格
| 方法 | 作用 |
|---|---|
size() |
获取元素个数 |
empty() |
判断是否为空(空返回 true) |
capacity() |
获取当前容量 |
resize(n) |
调整元素个数为 n,多删少补 0 |
reserve(n) |
预分配容量,避免频繁扩容 |
shrink_to_fit() |
释放多余容量,capacity=size |
-
本质 :封装了动态数组的类模板,内存连续存放,支持随机访问(和数组一样通过下标访问元素)。
-
特点 :
- 内存自动管理,无需手动释放;
- 支持动态扩容(元素超出容量时自动分配更大内存);
- 尾部增删元素效率极高,中间 / 头部增删需要移动元素,效率较低;
- 迭代器支持随机访问。
-
头文件 :使用 vector 必须包含头文件
cpp#include <vector> using namespace std; // 日常开发常用,简化代码二、vector 的定义与初始化
vector 支持多种初始化方式,覆盖开发中绝大多数场景:
cpp#include <iostream> #include <vector> using namespace std; int main() { // 1. 空容器初始化(最常用) vector<int> v1; // 2. 指定容量,初始值为0(数值类型) vector<int> v2(5); // 5个元素,值都为0 // 3. 指定容量+初始值 vector<int> v3(5, 10); // 5个元素,值都为10 // 4. 列表初始化(C++11及以上) vector<int> v4 = {1,2,3,4,5}; vector<int> v5{1,2,3}; // 5. 拷贝初始化 vector<int> v6(v4); // 拷贝v4所有元素 // 6. 区间初始化 vector<int> v7(v4.begin(), v4.begin()+3); // 拷贝v4前3个元素 return 0; }三、vector 核心常用 API
vector 的 API 分为访问元素、增删元素、容量操作、迭代器四大类,是必须掌握的核心。
1. 元素访问
表格
方法 作用 备注 v[i]访问第 i 个元素 不检查越界,效率高 v.at(i)访问第 i 个元素 检查越界,越界抛异常 v.front()获取第一个元素 容器非空时使用 v.back()获取最后一个元素 容器非空时使用 v.data()获取底层数组首地址 用于兼容 C 语言接口 示例:
cppvector<int> v = {10,20,30}; cout << v[1] << endl; // 20 cout << v.at(2) << endl; // 30 cout << v.front() << endl; // 10 cout << v.back() << endl; // 302. 增加元素
表格
方法 作用 效率 push_back(val)尾部添加元素 极高(O (1)) emplace_back(val)尾部原位构造元素 C++11,比 push_back 更高效 insert(pos, val)在迭代器 pos 处插入元素 低(O (n),需移动元素) insert(pos, n, val)在 pos 处插入 n 个 val 低 示例:
cppvector<int> v; v.push_back(1); // 尾部加1 v.emplace_back(2); // 尾部加2,推荐使用 v.insert(v.begin(), 0); // 头部插入0 v.insert(v.end(), 2, 3); // 尾部插入两个3 // 最终:0,1,2,3,33. 删除元素
表格
方法 作用 pop_back()删除最后一个元素 erase(pos)删除迭代器 pos 指向的元素 erase(beg, end)删除区间 [beg,end) 内的元素 clear()清空所有元素(容量不变) 示例:
cppvector<int> v = {1,2,3,4,5}; v.pop_back(); // 删除5 v.erase(v.begin()+1); // 删除2 v.clear(); // 清空所有元素4. 容量与大小操作
区分两个核心概念:
-
size :当前容器中实际元素的个数;
-
capacity :容器当前能容纳的最大元素个数(已分配的内存)。
表格
| 方法 | 作用 |
|---|---|
size() |
获取元素个数 |
empty() |
判断是否为空(空返回 true) |
capacity() |
获取当前容量 |
resize(n) |
调整元素个数为 n,多删少补 0 |
reserve(n) |
预分配容量,避免频繁扩容 |
shrink_to_fit() |
释放多余容量,capacity=size |
示例:
cpp
vector<int> v;
v.reserve(10); // 预分配10个元素的容量,提升效率
v.push_back(1);
cout << v.size() << endl; // 1
cout << v.capacity() << endl; // 10
v.resize(5); // 元素个数变为5,新增元素默认0
5. 迭代器(遍历专用)
vector 的迭代器是随机访问迭代器 ,支持++、--、+、-操作,和指针用法几乎一致。
常用遍历方式:
cpp
vector<int> v = {1,2,3,4};
// 方式1:下标遍历(最简单)
for(int i=0; i<v.size(); i++){
cout << v[i] << " ";
}
// 方式2:迭代器遍历(通用,所有容器都支持)
for(vector<int>::iterator it = v.begin(); it != v.end(); it++){
cout << *it << " ";
}
// 方式3:C++11范围for(最简洁)
for(int num : v){
cout << num << " ";
}
四、vector 底层原理:动态扩容机制
vector 的核心优势是动态扩容 ,但扩容不是按需增加,而是成倍分配内存(不同编译器规则不同):
- VS 编译器:扩容为原来的 1.5 倍;
- GCC 编译器:扩容为原来的 2 倍。
扩容流程:
- 当
size == capacity时,再次插入元素会触发扩容; - 申请一块更大的连续内存;
- 将旧内存的所有元素拷贝 / 移动到新内存;
- 释放旧内存,更新迭代器、指针、引用。
⚠️ 注意 :扩容会导致原有迭代器、指针、引用全部失效,使用时需要特别注意。
✅ 优化建议 :提前知道元素数量时,用reserve()预分配容量,避免多次扩容。
五、vector 存放自定义数据类型
vector 不仅能存放基本数据类型,还能存放自定义类、结构体:
cpp
#include <string>
// 自定义结构体
struct Student {
string name;
int age;
};
int main() {
vector<Student> v;
Student s1 = {"张三", 18};
v.push_back(s1);
// 访问自定义类型成员
cout << v[0].name << " " << v[0].age << endl;
return 0;
}
六、vector 常用算法
配合<algorithm>头文件,可直接使用 STL 算法操作 vector:
cpp
#include <algorithm>
vector<int> v = {3,1,4,1,5};
sort(v.begin(), v.end()); // 升序排序
reverse(v.begin(), v.end()); // 反转元素
find(v.begin(), v.end(), 4); // 查找元素4
七、vector 使用注意事项
- 避免在循环中频繁
push_back,优先用reserve预分配; - 中间 / 头部插入 / 删除效率低,大量操作时建议用
list; - 扩容后,旧的迭代器、指针、引用会失效,需要重新获取;
- 访问元素优先用
[](高效),需要安全检查时用at(); clear()只清空元素,不释放内存,想释放内存用shrink_to_fit()。
八、适用场景
- 需要随机访问元素(通过下标快速读取);
- 元素个数不确定,需要动态扩容;
- 主要在尾部增删元素;
- 替代传统静态数组,简化内存管理。
总结
- vector 是连续内存的动态数组,支持随机访问,尾部增删高效;
- 核心 API:
push_back、pop_back、insert、erase、size、capacity; - 区分
size(元素个数)和capacity(容量),reserve预分配容量优化性能; - 扩容会成倍分配内存,导致旧迭代器失效;
- 是 STL 最常用容器,优先用于动态数组场景。