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() 还是 0
  • capacity() 至少是 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() == 0
  • v.capacity() == 0

为什么有效

因为和一个空对象交换后,原来的大内存转移到临时对象,临时对象马上析构,内存就释放了。

适用场景

vector 特别大,而且你确定短期内不再需要这些容量。


一组最容易混淆的区别

clear() vs erase()

  • clear():删全部元素
  • erase():删部分元素

resize() vs reserve()

  • resize(n):真的把元素个数改成 n
  • reserve(n):只是预留空间,不增加元素

clear() vs shrink_to_fit()

  • clear():清元素,不一定清容量
  • shrink_to_fit():尝试缩容量,不改 size

面试里很常见的几个点

1. clear() 会释放内存吗?

标准层面:不保证释放容量
实践里:通常不会释放底层容量。


2. reserve()resize() 的本质区别?

  • reserve() 影响的是capacity
  • resize() 影响的是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 清的是 size
  • reserve 管的是 capacity
  • resize 改的是 size
  • swap(empty) 才是常见的“彻底释放”手段

结语

在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。

这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。

我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。

最后,想特别推荐一下我出版的书籍——《C++编程之禅:从理论到实践》。这是对博主C++ 系列博客内容的系统整理与升华,无论你是初学者还是有经验的开发者,都能在书中找到适合自己的成长路径。从C语言基础到C++20前沿特性,从设计哲学到实际案例,内容全面且兼具深度,更加入了心理学和禅宗哲理,帮助你用更好的心态面对编程挑战。
本书目前已在京东、当当等平台发售,推荐前往“清华大学出版社京东自营官方旗舰店”选购,支持纸质与电子书双版本。希望这本书能陪伴你在C++学习和成长的路上,不断精进,探索更多可能!感谢大家一路以来的支持和关注,期待与你在书中相见。


阅读我的CSDN主页,解锁更多精彩内容:泡沫的CSDN主页
在这里插入图片描述

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐