C++ vector 容器
在 C++ 标准库中,std::vector
是最常用的顺序容器(sequence container)之一,它封装了动态数组,能在尾部高效地插入和删除元素,并且提供随机访问。下面从基础到进阶分几个方面讲解它的用法与特性。
1. 引入 & 定义
#include <vector>
// 声明一个存放 int 的空 vector
std::vector<int> v1;
// 带初始大小的 vector,所有元素值为默认(0)
std::vector<int> v2(5);
// 带大小和初始值的 vector
std::vector<int> v3(5, 42); // {42,42,42,42,42}
// 从其他容器或数组构造
std::vector<int> v4(v3.begin(), v3.end());
int arr[] = {1,2,3};
std::vector<int> v5(std::begin(arr), std::end(arr));
<vector>
头文件;位于std
命名空间。- 模板参数
T
表示元素类型,还可传第三个模板参数自定义分配器(Allocator)。
2. 元素访问
v1 = {10, 20, 30};
// 下标访问(无越界检查)
int x = v1[1]; // 20
// at() 访问(带越界检查,越界抛出 std::out_of_range)
int y = v1.at(2); // 30
// 首尾元素
int first = v1.front(); // 等价 *v1.begin()
int last = v1.back(); // 等价 *(v1.end()-1)
// 原始数据指针
int* data = v1.data(); // C++11 起,指向连续内存首地址
3. 迭代器
// 正向迭代
for (auto it = v1.begin(); it != v1.end(); ++it) {
std::cout << *it << " ";
}
// 反向迭代
for (auto it = v1.rbegin(); it != v1.rend(); ++it) {
std::cout << *it << " ";
}
// C++11 范围 for
for (int& elem : v1) {
elem += 1;
}
4. 容量相关
v1.clear(); // 清空所有元素
bool empty = v1.empty();// 是否为空
size_t sz = v1.size(); // 当前元素个数
size_t cap = v1.capacity(); // 当前已分配内存能容纳的元素数
v1.reserve(100); // 预分配至少能容纳 100 个元素(避免多次扩容)
v1.shrink_to_fit(); // 尽量收缩 capacity 至 size(C++11)
- 动态扩容策略:当插入新元素超出
capacity()
时,一般按约 1.5–2 倍增长,分摊插入为均摊 O(1)。 reserve
可提前分配,减少扩容开销。
5. 修改器(Modifiers)
// 在尾部插入
v1.push_back(5); // 将 5 添加到末尾
v1.emplace_back(6); // 原地构造元素
// 在任意位置插入
auto it = v1.begin() + 1;
v1.insert(it, 42); // 单个元素
v1.insert(it, 3, 7); // 插入 3 个值为 7 的元素
v1.insert(it, v3.begin(), v3.end()); // 插入一个范围
// 删除
v1.pop_back(); // 删除末尾元素
v1.erase(v1.begin()+2);// 删除指定位置元素
v1.erase(v1.begin(), v1.begin()+2); // 删除一个范围
// 其他
v1.resize(8); // 改变 size,新增元素值为默认
v1.resize(8, 9); // 新增元素值为 9
v1.swap(v3); // 与另一个 vector 交换内容(O(1))
emplace_*
系列在容器内部直接构造对象,避免额外拷贝或移动。
6. 算法 & 适配器
std::vector
与 <algorithm>
中的算法深度集成:
#include <algorithm>
// 排序
std::sort(v1.begin(), v1.end());
// 查找
auto found = std::find(v1.begin(), v1.end(), 42);
if (found != v1.end()) { /* 找到 */ }
// 删除值为 0 的元素(erase–remove 惯用法)
v1.erase(std::remove(v1.begin(), v1.end(), 0), v1.end());
7. 与其他容器对比
特性 | vector | deque | list |
---|---|---|---|
随机访问 | O(1) | O(1) | O(n) |
头尾插入/删除 | 仅尾部 O(1) | 头尾 O(1) | 头中尾 O(1) |
插入/删除中间 | O(n) | O(n) | O(1) |
内存连续 | 是 | 否 | 否 |
- 若需要频繁在中间插入,考虑
std::list
或std::deque
;否则大多数场景下vector
性能最佳。
8. 性能优化建议
- 预留空间:
reserve(n)
减少扩容开销。 - 避免不必要的拷贝:如传参时用
const std::vector<T>&
,返回时可利用移动语义。 - 使用
emplace_*
:需要构造复杂对象时,避免额外构造–拷贝。 - 合适的初始大小:若已知元素数量,可直接用
vector<T> v(n);
或v.reserve(n)
。
小结
std::vector
是封装动态数组的顺序容器,支持高效的随机访问和尾部插入/删除。- 丰富的成员函数与
<algorithm>
结合,可完成排序、查找、删除等常见操作。 - 了解其容量管理与扩容策略,并合理使用
reserve
、emplace
,可在性能和安全性之间取得平衡。