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. 与其他容器对比

特性vectordequelist
随机访问O(1)O(1)O(n)
头尾插入/删除仅尾部 O(1)头尾 O(1)头中尾 O(1)
插入/删除中间O(n)O(n)O(1)
内存连续
  • 若需要频繁在中间插入,考虑 std::list 或 std::deque;否则大多数场景下 vector 性能最佳。

8. 性能优化建议

  1. 预留空间reserve(n) 减少扩容开销。
  2. 避免不必要的拷贝:如传参时用 const std::vector<T>&,返回时可利用移动语义。
  3. 使用 emplace_*:需要构造复杂对象时,避免额外构造–拷贝。
  4. 合适的初始大小:若已知元素数量,可直接用 vector<T> v(n); 或 v.reserve(n)

小结

  • std::vector 是封装动态数组的顺序容器,支持高效的随机访问和尾部插入/删除。
  • 丰富的成员函数与 <algorithm> 结合,可完成排序、查找、删除等常见操作。
  • 了解其容量管理与扩容策略,并合理使用 reserveemplace,可在性能和安全性之间取得平衡。

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注