【C++ 基础 】std::vector 常见操作区别
目录标题
std::vector 常见操作区别
| 操作 | 改变 size | 改变 capacity | 是否删除元素 | 典型用途 |
|---|---|---|---|---|
clear() |
是,变成 0 | 通常不变 | 是 | 清空内容,保留容量以便复用 |
erase() |
是 | 不变 | 是,删指定位置/区间 | 删除部分元素 |
resize(n) |
是 | 可能变 | 可能删,也可能新增 | 调整元素个数 |
reserve(n) |
否 | 可能变大 | 否 | 预留容量,避免频繁扩容 |
shrink_to_fit() |
否 | 尝试变小 | 否 | 请求释放多余容量 |
swap(empty) |
是 | 通常变成 0 | 是 | 强力释放内存 |
1. clear()
作用
清空所有元素,但通常不释放容量。
std::vector<int> v = {1, 2, 3, 4};
v.clear();
结果通常是:
v.size() == 0
v.capacity() // 大概率还在
特点
- 所有元素被销毁
- 迭代器、引用、指针基本都失效
- 后续继续
push_back()可能不需要重新分配内存
适用场景
你后面还要继续用这个 vector,只是先把内容清掉。
2. erase()
作用
删除某一个元素或一段区间元素。
std::vector<int> v = {10, 20, 30, 40, 50};
v.erase(v.begin() + 1); // 删除 20
结果:
{10, 30, 40, 50}
删除区间:
v.erase(v.begin() + 1, v.begin() + 3);
特点
size()会变小capacity()不变- 被删位置后面的元素会前移
- 从删除点开始后的迭代器会失效
复杂度
- 一般是线性复杂度,因为要搬移后面的元素
适用场景
删除中间某些元素,而不是全部清空。
3. resize(n)
作用
把 vector 的元素个数改成 n。
变小
std::vector<int> v = {1, 2, 3, 4, 5};
v.resize(3);
结果:
{1, 2, 3}
后两个元素被销毁。
变大
std::vector<int> v = {1, 2};
v.resize(5);
结果通常:
{1, 2, 0, 0, 0}
对于 int 这种基础类型,新元素会值初始化。
也可以指定默认值:
v.resize(5, 99); // {1,2,99,99,99}
特点
size()一定变成目标值capacity()可能增大,但一般不会因为变小而自动减小- 本质是“调整元素数量”,不是“预留空间”
适用场景
你明确需要让容器里现在就有 n 个元素。
4. reserve(n)
作用
预留容量,避免后面频繁扩容。
std::vector<int> v;
v.reserve(1000);
这时候:
size()还是0capacity()至少是1000
特点
- 不会创建元素
- 只是分配足够的底层空间
- 后面大量
push_back()时性能更稳定
常见误区
很多人以为 reserve(100) 后可以直接 v[0] = 1;
这是错的,因为:
capacity()够了- 但
size()还是 0 - 没有真正存在的元素可以下标访问
错误示例:
std::vector<int> v;
v.reserve(10);
v[0] = 1; // 未定义行为
正确写法:
v.push_back(1);
或者:
v.resize(10);
v[0] = 1;
适用场景
你知道大概要放多少元素,想减少扩容次数。
5. shrink_to_fit()
作用
请求把多余容量缩掉。
std::vector<int> v;
v.reserve(1000);
v.resize(10);
v.shrink_to_fit();
理论上希望把容量缩到接近 size()。
重点
标准不保证一定成功。
也就是说它只是“请求”,实现可以不理你。
适用场景
你想尽量缩容,但不要求绝对成功。
6. `swap(empty)``
作用
通常用于强制释放大部分内存。
std::vector<int> v(1000000);
std::vector<int>().swap(v);
结果通常:
v.size() == 0v.capacity() == 0
为什么有效
因为和一个空对象交换后,原来的大内存转移到临时对象,临时对象马上析构,内存就释放了。
适用场景
vector 特别大,而且你确定短期内不再需要这些容量。
一组最容易混淆的区别
clear() vs erase()
clear():删全部元素erase():删部分元素
resize() vs reserve()
resize(n):真的把元素个数改成nreserve(n):只是预留空间,不增加元素
clear() vs shrink_to_fit()
clear():清元素,不一定清容量shrink_to_fit():尝试缩容量,不改 size
面试里很常见的几个点
1. clear() 会释放内存吗?
标准层面:不保证释放容量。
实践里:通常不会释放底层容量。
2. reserve() 和 resize() 的本质区别?
reserve()影响的是capacityresize()影响的是size
3. 删除中间元素为什么慢?
因为 vector 底层是连续内存,删掉中间元素后,后面的元素通常要整体前移。
4. 为什么 push_back() 有时会导致指针/迭代器失效?
因为扩容时会重新申请一块更大的连续内存,再把旧元素搬过去,原地址失效。
实战建议
场景 1:循环里反复复用临时数组
std::vector<int> buf;
buf.reserve(1024);
for (...) {
buf.clear();
// 继续填充
}
这样比较高效。
场景 2:临时吃进了超大数据,后面不再需要大容量
std::vector<int> v = load_big_data();
std::vector<int>().swap(v);
场景 3:已知大概数量
std::vector<int> v;
v.reserve(10000);
for (int i = 0; i < 10000; ++i) {
v.push_back(i);
}
这样能减少扩容开销。
最后给你一个速记版
clear() // 清空元素,size=0,capacity通常不变
erase() // 删除指定元素/区间
resize(n) // 改元素数量,可能补元素,可能删元素
reserve(n) // 预留容量,不创建元素
shrink_to_fit() // 请求缩容,不保证成功
swap(empty) // 通常可真正释放内存
一句话记忆
- size 是当前有多少元素
- capacity 是最多能装多少而不扩容
clear清的是 sizereserve管的是 capacityresize改的是 sizeswap(empty)才是常见的“彻底释放”手段
结语
在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。
这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。
我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。
最后,想特别推荐一下我出版的书籍——《C++编程之禅:从理论到实践》。这是对博主C++ 系列博客内容的系统整理与升华,无论你是初学者还是有经验的开发者,都能在书中找到适合自己的成长路径。从C语言基础到C++20前沿特性,从设计哲学到实际案例,内容全面且兼具深度,更加入了心理学和禅宗哲理,帮助你用更好的心态面对编程挑战。
本书目前已在京东、当当等平台发售,推荐前往“清华大学出版社京东自营官方旗舰店”选购,支持纸质与电子书双版本。希望这本书能陪伴你在C++学习和成长的路上,不断精进,探索更多可能!感谢大家一路以来的支持和关注,期待与你在书中相见。
阅读我的CSDN主页,解锁更多精彩内容:泡沫的CSDN主页
更多推荐





所有评论(0)