当前位置: 首页 > 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.dtcms.com/a/320181.html

相关文章:

  • 一个程序通过 HTTP 协议调用天气 API,解析 JSON 格式的天气数据,提取关键信息并格式化输出:日期、天气状况、温度范围、风向、湿度等核心气象数据。
  • 1688 商品详情接口开发实战:从平台特性到高可用实现
  • Redis最新安装教程(WindowsLinux)
  • 对基带信号进行调制的原因及通俗理解
  • HR人才测评工具,卡特尔16pf性格测试
  • Numpy科学计算与数据分析:Numpy数学函数入门与实践
  • 我爱发明之Linux下使用Conky在桌面显示Spotify状态及封面字符画
  • 无损音乐下载器!(电脑)绿色免费,无限下载,无损音质
  • 是否将标签页tag信息存储在Redux store中还是仅存储在hook的state中
  • AI题解5
  • 什么是0.5米分辨率卫星影像数据?
  • 一文学会c++继承 组合
  • [优选算法专题一双指针——两数之和](双指针和哈希表)
  • 解决GitHub push失败-Failed to connect to github.com port 443: Timed out
  • 亚马逊卖家反馈机制变革:纯星级评级时代的合规挑战与运营重构
  • SOMGAN:用自组织映射改善GAN的模式探索能力
  • 自然语言处理×第四卷:文本特征与数据——她开始准备:每一次输入,都是为了更像你地说话
  • python selenium环境安装
  • Python自动化测试selenium指定截图文件名方法
  • MySQL 备份利器 Xtrabackup 全解析:从部署到恢复的实战指南
  • 视觉语言模型的空间推理缺陷——AI 在医学扫描中难以区分左右
  • 《CogAgent: A Visual Language Model for GUI Agents》论文精读笔记
  • Vue 3 入门教程 9 - 表单处理
  • 8、Redis的HyperLogLog、事务Multi、管道Pipeline,以及Redis7.0特性
  • DoubleTrouble靶机
  • 【R语言】重新绘制高清MaxEnt的单因素响应曲线图像
  • 最佳左前缀法则(Optimal Left-Prefix Rule)
  • 【Dijkstra】 Shortest Routes I
  • 5种将Android联系人传输到电脑的方法
  • 《C语言》函数练习题--4