1.常见接口使用
初始化 vector
使用 std::vector 需要包含头文件 <vector>。初始化可以通过多种方式完成:
cpp
#include <vector>
std::vector<int> vec1; // 空 vector
std::vector<int> vec2(5, 10); // 5 个元素,每个值为 10
std::vector<int> vec3 = {1, 2, 3, 4, 5}; // 初始化列表
添加元素
使用 push_back 在末尾添加元素:
cpp
vec1.push_back(6); // vec1 现在为 {6}
使用 emplace_back 避免临时对象构造:
cpp
vec1.emplace_back(7); // vec1 现在为 {6, 7}
访问元素
通过下标或 at 访问元素:
cpp
int val1 = vec3[2]; // val1 = 3
int val2 = vec3.at(3); // val2 = 4
使用 front 和 back 访问首尾元素:
cpp
int first = vec3.front(); // first = 1
int last = vec3.back(); // last = 5
修改元素
通过下标或迭代器修改元素:
cpp
vec3[1] = 20; // vec3 现在为 {1, 20, 3, 4, 5}
删除元素
使用 pop_back 删除末尾元素:
cpp
vec3.pop_back(); // vec3 现在为 {1, 20, 3, 4}
使用 erase 删除指定位置元素:
cpp
vec3.erase(vec3.begin() + 1); // vec3 现在为 {1, 3, 4}
容量操作
检查 vector 是否为空:
cpp
bool isEmpty = vec1.empty(); // isEmpty = false
获取 vector 大小和容量:
cpp
size_t size = vec3.size(); // size = 3
size_t capacity = vec3.capacity(); // 当前分配的存储空间
调整 vector 大小:
cpp
vec3.resize(5); // vec3 现在为 {1, 3, 4, 0, 0}
迭代器操作
使用迭代器遍历 vector:
cpp
for (auto it = vec3.begin(); it != vec3.end(); ++it) {
std::cout << *it << " ";
}
使用范围 for 循环:
cpp
for (int num : vec3) {
std::cout << num << " ";
}
清空 vector
使用 clear 清空所有元素:
cpp
vec3.clear(); // vec3 现在为空
交换 vector
使用 swap 交换两个 vector 内容:
cpp
std::vector<int> vec4 = {10, 20};
vec3.swap(vec4); // vec3 现在为 {10, 20}, vec4 为空
2.vector 迭代器失效问题
迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。
核心本质:vector 底层是连续动态数组,当内存重新分配、元素移动后,原迭代器指向的位置 / 内存无效,再使用就会崩溃、乱码。
场景 1:扩容操作 → 所有迭代器全部失效
触发条件执行 push_back / insert / reserve / resize 时,当前容量不足,vector 会:
开辟一块新的更大内存把旧数据拷贝到新内存释放旧内存。
后果:所有旧迭代器变成野指针,完全失效。
错误代码
cpp
vector<int> v = {1,2,3};
auto it = v.begin(); // 指向旧内存
v.push_back(4); // 容量不足,触发扩容,旧内存被释放!
// it 已经是野指针,访问崩溃
cout << *it << endl;
解决方案
扩容后重新获取迭代器:
cpp
auto it = v.begin();
v.push_back(4);
it = v.begin(); // 重新赋值,指向新内存
场景 2:insert 插入元素 → 插入位置及之后的迭代器失效
触发条件:在任意位置插入元素(即使不扩容),插入位置后面的所有元素会整体向后移动。
后果:插入位置及之后的迭代器,指向的元素位置已经改变,直接失效。
cpp
vector<int> v = {1,2,3};
auto it = v.begin() + 1; // 指向 2
v.insert(it, 10); // 插入后,元素后移,it 失效
// 访问失效迭代器,未定义行为
cout << *it << endl;
解决方案:
insert 会返回新的有效迭代器,用它覆盖旧迭代器:
cpp
it = v.insert(it, 10); // 用返回值更新迭代器
场景 3:erase 删除元素 → 删除位置及之后的迭代器失效
触发条件:删除元素后,删除位置后面的所有元素会整体向前移动。
后果:删除位置及之后的迭代器直接失效。
⚠️ 经典坑:循环删除元素时直接 it++,必崩溃!
错误代码(循环删除偶数,必错)
cpp
vector<int> v = {1,2,3,4};
for(auto it = v.begin(); it != v.end(); it++){
if(*it % 2 == 0){
v.erase(it); // 删除后 it 失效,再 it++ 直接崩溃
}
}
解决方案
erase 会返回下一个有效迭代器,直接赋值即可:
cpp
for(auto it = v.begin(); it != v.end(); ){
if(*it % 2 == 0){
it = v.erase(it); // 用返回值更新,不用手动++
}else{
it++; // 不删除时再++
}
}
总结(必背)
1.扩容 → 全部迭代器失效 → 重新获取。
2.插入 / 删除 → 操作位置及之后失效 → 用 insert/erase 返回值更新。
3.迭代器使用原则:只要修改了 vector 结构(增删扩容),就不要使用旧迭代器。
谢谢