C++ vector 完全指南:从入门到精通
vector 是 C++ 中最强大且最常用的容器之一,本文将带你全面掌握 vector 的使用技巧!
一、什么是 vector?
std::vector
是 C++ 标准模板库(STL)中的动态数组容器,它能够自动管理内存,在运行时根据需要动态调整大小。相比于传统数组,vector 提供了更强大的功能和更便捷的操作方式。
vector 的核心优势
-
动态扩容:自动处理内存分配和释放
-
随机访问:支持 O(1) 复杂度的元素访问
-
丰富接口:提供多种操作方法
-
类型安全:模板化的容器保证类型安全
-
内存连续:元素在内存中连续存储
二、创建和初始化 vector
1. 基本声明方式
#include <vector>
using namespace std;// 创建空vector
vector<int> nums;// 创建指定大小的vector(默认初始化为0)
vector<double> prices(5); // 5个0.0// 创建指定大小并初始化的vector
vector<string> names(3, "Unknown"); // 3个"Unknown"
2. 初始化列表(C++11起)
// 列表初始化
vector<int> primes = {2, 3, 5, 7, 11};// 从数组初始化int arr[ ] = {1, 2, 3, 4, 5};vector<int> vec(arr, arr + sizeof(arr)/sizeof(arr[0]));// 复制另一个vector
vector<int> copyVec = primes;
三、vector 的基本操作
1. 添加元素
vector<int> v;// 尾部添加元素
v.push_back(10); // v: [10]
v.push_back(20); // v: [10, 20]
v.push_back(30); // v: [10, 20, 30]// 高效构造并添加(C++11)
v.emplace_back(40); // v: [10, 20, 30, 40]// 在指定位置插入
v.insert(v.begin() + 1, 15); // v: [10, 15, 20, 30, 40]
2. 访问元素
// 使用下标访问(不检查边界)
cout << v[0]; // 10// 使用at()访问(边界检查)
cout << v.at(1); // 15// 访问首尾元素
cout << v.front(); // 10
cout << v.back(); // 40// 遍历vector(C++11范围for循环)
for (int num : v) {cout << num << " ";
}
// 输出: 10 15 20 30 40
3. 删除元素
// 删除尾部元素
v.pop_back(); // v: [10, 15, 20, 30]// 删除指定位置元素
v.erase(v.begin() + 1); // v: [10, 20, 30]// 删除指定范围的元素
v.erase(v.begin(), v.begin() + 2); // v: [30]// 清空vectorv.clear(); // v: [ ]
4. 大小与容量管理
vector<int> vec = {1, 2, 3};cout << "元素数量: " << vec.size(); // 3
cout << "最大容量: " << vec.capacity(); // 可能大于3// 调整大小(多出部分默认初始化为0)
vec.resize(5); // vec: [1, 2, 3, 0, 0]// 预留空间(避免多次重分配)
vec.reserve(100); // 容量至少为100// 检查是否为空
if (vec.empty()) {cout << "vector为空!";
}
四、vector 内存管理机制
1. 动态扩容原理
vector 在内存中连续存储元素,当添加元素超过当前容量时:
-
分配新的更大的内存块(通常是当前大小的1.5-2倍)
-
将原有元素复制/移动到新内存
-
释放原有内存
-
添加新元素
vector<int> v;
cout << "初始容量: " << v.capacity() << endl; // 0for (int i = 0; i < 10; i++) {v.push_back(i);cout << "大小: " << v.size() << " 容量: " << v.capacity() << endl;
}
典型输出:
大小:1 容量:1
大小:2 容量:2
大小:3 容量:4
大小:4 容量:4
大小:5 容量:8
大小:6 容量:8
大小:7 容量:8
大小:8 容量:8
大小:9 容量:16
大小:10 容量:16
2. 优化技巧:reserve()
// 低效方式(可能多次重分配)
vector<int> inefficient;
for (int i = 0; i < 1000; i++) {inefficient.push_back(i);
}// 高效方式(一次性预留空间)
vector<int> efficient;
efficient.reserve(1000); // 避免多次重分配
for (int i = 0; i < 1000; i++) {efficient.push_back(i);
}
五、迭代器使用
vector<int> nums = {10, 20, 30, 40, 50};// 1. 常规迭代器
cout << "正向遍历: ";
for (auto it = nums.begin(); it != nums.end(); ++it) {cout << *it << " ";
}// 2. 反向迭代器
cout << "\n反向遍历: ";
for (auto rit = nums.rbegin(); rit != nums.rend(); ++rit) {cout << *rit << " ";
}// 3. 常量迭代器(防止修改)
for (auto cit = nums.cbegin(); cit != nums.cend(); ++cit) {// *cit = 100; // 错误!不能修改cout << *cit << " ";
}
六、vector 高级技巧
1. 二维 vector(矩阵)
// 创建3x4矩阵(初始化为0)
vector<vector<int>> matrix(3, vector<int>(4, 0));// 访问元素
matrix[1][2] = 5; // 第2行第3列// 遍历二维vector
for (const auto& row : matrix) {for (int num : row) {cout << num << " ";}cout << endl;
}
2. 使用 swap 释放内存
vector<int> bigVec(1000000); // 占用大量内存// 传统clear()不会释放内存
bigVec.clear();
cout << "容量: " << bigVec.capacity(); // 仍然很大// 使用swap技巧释放内存
vector<int>().swap(bigVec);
cout << "容量: " << bigVec.capacity(); // 0
3. 元素排序和搜索
vector<int> numbers = {5, 3, 8, 1, 4};// 排序
sort(numbers.begin(), numbers.end()); // [1, 3, 4, 5, 8]// 二分查找(要求已排序)
if (binary_search(numbers.begin(), numbers.end(), 5)) {cout << "5存在于vector中";
}// 查找元素位置
auto it = find(numbers.begin(), numbers.end(), 4);
if (it != numbers.end()) {cout << "找到4,位置: " << distance(numbers.begin(), it);
}
七、vector 使用注意事项
迭代器失效问题
-
添加元素可能导致所有迭代器失效
-
删除元素会使被删除元素之后的迭代器失效
避免在循环中插入/删除
// 危险!循环中删除可能导致迭代器失效
for (auto it = vec.begin(); it != vec.end(); ) {if (*it % 2 == 0) {it = vec.erase(it); // 正确方式} else {++it;}
}
对象 vs 指针
-
存储对象:适用于小型对象
-
存储指针:适用于大型对象或多态
性能考虑
操作 | 时间复杂度 |
随机访问 | O(1) |
尾部插入/删除 | O(1) |
头部插入/删除 | O(n) |
中间插入/删除 | O(n) |
八、完整示例程序
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;int main() {// 创建并初始化vectorvector<int> scores = {85, 92, 78, 90, 88};// 添加元素scores.push_back(95);scores.insert(scores.begin(), 80);// 删除元素scores.pop_back();scores.erase(scores.begin() + 2);// 遍历vectorcout << "当前成绩: ";for (int score : scores) {cout << score << " ";}cout << endl;// 排序sort(scores.begin(), scores.end());// 查找auto it = find(scores.begin(), scores.end(), 90);if (it != scores.end()) {cout << "找到90分,位置: " << distance(scores.begin(), it) << endl;}// 容量管理cout << "元素数量: " << scores.size() << endl;scores.reserve(20);cout << "当前容量: " << scores.capacity() << endl;return 0;
}
总结
vector 是 C++ 中最常用且功能强大的容器之一,其核心优势在于:
-
动态内存管理,简化开发
-
连续存储提供高效的随机访问
-
丰富的成员函数满足各种需求
-
与算法库完美配合
掌握 vector 的使用是成为高效 C++ 开发者的关键一步。通过合理使用 reserve() 优化性能,注意迭代器失效问题,并善用 STL 算法,你可以在项目中充分发挥 vector 的强大功能!