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 ”搬家“时,它尝试使用:
✅ 移动构造函数(如果存在且
noexcept
)→ 更快;❌ 否则使用 拷贝构造函数 → 更慢;
因此,如果你自定义了类并希望它和 vector 搭配高效使用,请提供移动构造函数并标记为 noexcept
。
因为每次扩容都要搬所有元素,所以:
如果你知道 vector 大概需要多少元素,建议提前调用
v.reserve(n);
来减少扩容次数。
std::vector<int> v;
v.reserve(1000); // 预分配1000个容量,避免多次扩容
这是性能优化常用手段,尤其适合:
你提前知道大概元素个数
要插入很多元素
类型比较复杂(移动/拷贝成本高)