C++的vector是标准模板库STL中的序列式容器,本质是可动态扩容的数组,不需要提前指定固定大小,元素在内存中连续存储,支持随机访问,兼顾了数组的高效访问特性和动态大小调整的灵活性,是日常开发中使用频率极高的容器之一。

vector的基础初始化方式
vector提供了多种初始化方式,可根据实际需求选择:
- 默认初始化:创建一个空的vector,不包含任何元素
- 指定大小和初始值初始化:创建包含n个元素,每个元素都为指定值的vector
- 迭代器范围初始化:用其他容器的迭代器区间初始化vector
- 初始化列表初始化:用花括号内的元素列表直接初始化
以下是不同初始化方式的代码示例:
#include <vector>
#include <iostream>
using namespace std;
int main() {
// 默认初始化,空vector
vector<int> v1;
// 初始化5个元素,每个元素为10
vector<int> v2(5, 10);
// 用数组迭代器初始化
int arr[] = {1, 2, 3, 4};
vector<int> v3(arr, arr + 4);
// 初始化列表初始化
vector<int> v4 = {1, 3, 5, 7, 9};
return 0;
}
vector的常用元素操作
添加元素
vector添加元素常用push_back方法,在容器尾部追加元素,若当前容量不足会自动扩容:
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v;
// 尾部添加元素
v.push_back(10);
v.push_back(20);
v.push_back(30);
for (int num : v) {
cout << num << " ";
}
// 输出:10 20 30
return 0;
}
访问元素
vector支持两种访问方式,一种是和下标运算符[],另一种是at方法:
operator[]:不做边界检查,访问越界会导致未定义行为at():会做边界检查,访问越界会抛出out_of_range异常
代码示例:
#include <vector>
#include <iostream>
#include <stdexcept>
using namespace std;
int main() {
vector<int> v = {1, 2, 3};
// 下标访问
cout << v[0] << endl; // 输出1
// at方法访问
cout << v.at(1) << endl; // 输出2
try {
// 访问越界,at会抛异常
cout << v.at(5) << endl;
} catch (out_of_range& e) {
cout << "访问越界:" << e.what() << endl;
}
return 0;
}
删除元素
常用的删除操作有pop_back删除尾部元素,以及erase删除指定位置或区间的元素:
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
// 删除尾部元素
v.pop_back(); // 现在v为{1,2,3,4}
// 删除第二个元素(迭代器指向的位置)
v.erase(v.begin() + 1); // 现在v为{1,3,4}
// 删除前两个元素
v.erase(v.begin(), v.begin() + 2); // 现在v为{4}
for (int num : v) {
cout << num << " ";
}
// 输出:4
return 0;
}
vector的容量与大小管理
vector有两个容易混淆的属性:size和capacity:
size():返回当前容器中实际存储的元素个数capacity():返回当前容器在不重新分配内存的情况下最多能存储的元素个数
当size超过capacity时,vector会自动重新分配更大的内存空间,将原有元素拷贝到新空间,然后释放旧空间,这个过程会有一定的性能开销。可以通过reserve方法提前预留容量,减少扩容次数:
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v;
cout << "初始size:" << v.size() << ",初始capacity:" << v.capacity() << endl;
// 输出:初始size:0,初始capacity:0
// 提前预留10个元素的容量
v.reserve(10);
cout << "预留后size:" << v.size() << ",capacity:" << v.capacity() << endl;
// 输出:预留后size:0,capacity:10
// 添加5个元素,不会触发扩容
for (int i = 0; i < 5; i++) {
v.push_back(i);
}
cout << "添加元素后size:" << v.size() << ",capacity:" << v.capacity() << endl;
// 输出:添加元素后size:5,capacity:10
return 0;
}
vector的遍历方式
vector支持多种遍历方式,可根据场景选择:
下标遍历
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4};
for (int i = 0; i < v.size(); i++) {
cout << v[i] << " ";
}
// 输出:1 2 3 4
return 0;
}
迭代器遍历
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4};
for (auto it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
// 输出:1 2 3 4
return 0;
}
范围for遍历
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4};
for (int num : v) {
cout << num << " ";
}
// 输出:1 2 3 4
return 0;
}
vector使用注意事项
- 不要在遍历vector的同时调用
erase删除元素,会导致迭代器失效,正确做法是在erase后接收返回的新迭代器 - 如果明确知道要存储的元素数量,提前用
reserve预留容量,避免多次扩容带来的性能损耗 - 用
empty方法判断vector是否为空,不要直接用size() == 0,语义更清晰 - vector存储自定义类型时,该类型需要支持拷贝构造,因为扩容时会拷贝原有元素到新内存空间
以下是迭代器失效的正确处理方式示例:
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
// 删除所有偶数元素
for (auto it = v.begin(); it != v.end(); ) {
if (*it % 2 == 0) {
// erase返回下一个有效迭代器
it = v.erase(it);
} else {
it++;
}
}
for (int num : v) {
cout << num << " ";
}
// 输出:1 3 5
return 0;
}