当前位置: 首页 > news >正文

C++ vector 扩容时到底发生了什么?

  std::vector 是 C++ STL 中最常用、最强大的动态数组容器之一,它支持自动增长大小,但你有没有思考过:

当我们不断 push_back(),vector 到底是如何“变大”的?是原地追加?还是整体搬家?

        这篇文章带你深入理解:vector 扩容时,底层到底发生了什么?

一、vector 是什么?

        简单来说,std::vector 就是一个 自动扩容的数组,它管理着一段连续的堆内存,其核心数据结构大致如下:

template<typename T>
class vector {T* _data;       // 指向数组起始地址size_t _size;   // 当前元素个数size_t _capacity; // 当前分配的容量
};

二、push_back 是怎么插入元素的?

        当我们调用:

std::vector<int> v;
v.push_back(42);

        执行流程如下:

检查当前 size 是否小于 capacity

是:在末尾插入新元素

否:触发扩容

三、vector 扩容时做了哪些事?

真实发生的步骤:

        当 capacity 不够时,vector 会:

1. 分配一块新的、更大的内存(通常是原容量的2倍)
2. 将旧数据“拷贝”或“移动”到新内存中
3. 析构旧元素(如果是对象)
4. 释放原来的内存
5. 插入新元素

        不是在原地追加,而是“整体搬家”

代码示例:打印容量变化

#include <iostream>
#include <vector>int main() {std::vector<int> v;for (int i = 0; i < 10; ++i) {std::cout << "Before push_back(" << i << ") ";std::cout << "size: " << v.size() << ", capacity: " << v.capacity() << '\n';v.push_back(i);}
}

输出示例(不同IDE输出不同):

Before push_back(0) size: 0, capacity: 0
Before push_back(1) size: 1, capacity: 1
Before push_back(2) size: 2, capacity: 2
Before push_back(3) size: 3, capacity: 4
Before push_back(5) size: 5, capacity: 8
...

说明:

  • 容量是 跳跃式增长

  • 每次超过容量都会触发整体搬迁(拷贝/移动)

  • 所以扩容是很昂贵的操作,特别是元素很多或类型复杂时

当 vector ”搬家“时,它尝试使用:

  1. 移动构造函数(如果存在且 noexcept)→ 更快;

  2. ❌ 否则使用 拷贝构造函数 → 更慢;

        因此,如果你自定义了类并希望它和 vector 搭配高效使用,请提供移动构造函数并标记为 noexcept

        因为每次扩容都要搬所有元素,所以:

如果你知道 vector 大概需要多少元素,建议提前调用 v.reserve(n); 来减少扩容次数。

std::vector<int> v;
v.reserve(1000); // 预分配1000个容量,避免多次扩容

这是性能优化常用手段,尤其适合:

  • 你提前知道大概元素个数

  • 要插入很多元素

  • 类型比较复杂(移动/拷贝成本高)

http://www.lryc.cn/news/613382.html

相关文章:

  • 纯本地AI知识库搭建:DeepSeek-R1+AnythingLLM全流程
  • priority_queue的使用和模拟
  • Kotlin中String的==相等比较符
  • C语言sprintf、strcmp、strcpy、strcat函数详解:字符串操作的核心工具
  • 「日拱一码」045 机器学习-因果发现算法
  • 力扣238:除自身之外数组的乘积
  • LeetCode算法日记 - Day 4: 三数之和、四数之和
  • 力扣300:最长递增子序列
  • 优选算法 力扣 LCR 179. 查找总价格为目标值的两个商品 双指针降低时间复杂度 C++题解 每日一题
  • Cesium粒子系统模拟风场动态效果
  • 【Zephyr】02_从零教你开发芯片级ADC驱动(HAL层篇)
  • 第三章:【springboot】框架介绍MyBatis
  • 恒虚警检测(CFAR)仿真:杂波边缘与多目标场景分析
  • 在新建word中使用以前文件中的列表样式
  • java中override和overload的区别
  • Java 大视界 -- Java 大数据在智能安防门禁系统中的人员行为分析与异常事件预警(385)
  • AR技术:制造业质量控制的“智能革新”
  • Redis最新安装教程(WindowsLinux)
  • Kubernetes(k8s)之Service服务
  • SpringBoot的优缺点
  • 【更新被拒绝,因为推送的一个分支的最新提交落后于其对应的远程分支。】
  • VLMEvalKit使用记录
  • 公开致歉声明
  • P1690 贪婪的 Copy
  • idea工具maven下载报错:PKIX path building failed,配置忽略SSL检查
  • 量子计算入门 | 量子力学的发展
  • 如何将普通HTTP API接口改造为MCP服务器
  • list类
  • SQL注入攻击基础
  • Cookie和Session是什么?有什么区别?