一、vector 类型的简介
vector 是 C++ 标准模板库(STL)中最常用的顺序容器之一,底层实现为 动态数组。它提供动态增长、随机访问、高效末尾插入等特性。
1.1 基本先容
- #include <vector>
- std::vector<int> numbers;
复制代码
1.2 常见用法示例
初始化方式
- std::vector<int> v1; // 空向量
- std::vector<int> v2(5); // 5个默认值(0)
- std::vector<int> v3(5, 42); // 5个 42
- std::vector<int> v4 = {1, 2, 3, 4}; // 列表初始化
复制代码 常用操纵
- v1.push_back(10); // 尾部添加元素
- v1.pop_back(); // 删除最后一个元素
- v1.size(); // 元素数量
- v1.empty(); // 是否为空
- v1.clear(); // 清空所有元素
- v1.at(2); // 安全访问第3个元素(带边界检查)
- v1[2]; // 快速访问第3个元素(无检查)
复制代码 遍历方式
- for (size_t i = 0; i < v1.size(); ++i)
- std::cout << v1[i] << std::endl;
- for (int x : v1) // C++11 范围循环
- std::cout << x << std::endl;
复制代码 1.3 常见成员函数简表
二、vector 数据的插入
std::vector 提供多种方式将数据插入容器中,适用于不同的使用场景(如单个元素插入、批量插入、自定义位置插入等)。
2.1 push_back() —— 在尾部插入一个元素
特点:时间复杂度均派为 O(1)
示例:
- std::vector<int> v;
- v.push_back(10);
- v.push_back(20); // v = {10, 20}
复制代码 2.2 emplace_back() —— 在尾部“就地”构造对象
特点:
示例:
- std::vector<std::pair<int, std::string>> v;
- v.emplace_back(1, "Alice"); // 直接构造 pair(1, "Alice")
复制代码 2.3 insert() —— 在任意位置插入一个或多个元素
重载形式包括:
插入单个元素
- std::vector<int> v = {1, 2, 4};
- v.insert(v.begin() + 2, 3); // v = {1, 2, 3, 4}
复制代码 插入多个雷同元素
- v.insert(v.begin(), 3, 100); // 插入3个100在开头
复制代码 插入另一 vector 的一段范围
- std::vector<int> v1 = {1, 2};
- std::vector<int> v2 = {10, 20, 30};
- v1.insert(v1.end(), v2.begin(), v2.end()); // v1 = {1, 2, 10, 20, 30}
复制代码 2.4 emplace() —— 在任意位置就地构造对象
雷同于 insert(),但对象是“就地构造”而非拷贝。
示例:
- std::vector<std::pair<int, std::string>> v;
- v.emplace(v.begin(), 1, "Bob"); // 插入 pair(1, "Bob") 到开头
复制代码 2.5 assign() —— 更换整个 vector 的内容
注意这是更换整个内容,不是插入。
- std::vector<int> v;
- v.assign(5, 42); // v = {42, 42, 42, 42, 42}
复制代码 插入方式对比表
三、vector 数据的遍历
3.1 范围-based for 循环(C++11 起)
- #include <vector>
- #include <iostream>
- std::vector<int> vec = {1, 2, 3, 4, 5};
- for (int value : vec) {
- std::cout << value << " ";
- }
复制代码 3.2 使用下标访问
- for (size_t i = 0; i < vec.size(); ++i) {
- std::cout << vec[i] << " ";
- }
复制代码 也可以用 at() 提供边界查抄:
- for (size_t i = 0; i < vec.size(); ++i) {
- std::cout << vec.at(i) << " ";
- }
复制代码 3.3 使用迭代器
- for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
- std::cout << *it << " ";
- }
复制代码 假如不需要修改数据,可使用 const_iterator:
- for (std::vector<int>::const_iterator it = vec.cbegin(); it != vec.cend(); ++it) {
- std::cout << *it << " ";
- }
复制代码 3.4 使用 std::for_each 和 Lambda(C++11 起)
- #include <algorithm>
- std::for_each(vec.begin(), vec.end(), [](int value) {
- std::cout << value << " ";
- });
复制代码 四、vector 数据的删除
4.1 删除尾部元素:pop_back()
- std::vector<int> vec = {1, 2, 3};
- vec.pop_back(); // 删除最后一个元素(3)
复制代码 4.2 按下标删除一个元素:erase(iterator)
- std::vector<int> vec = {10, 20, 30, 40};
- vec.erase(vec.begin() + 2); // 删除索引为2的元素(30)
复制代码 4.3 删除一个区间:erase(begin, end)
- std::vector<int> vec = {1, 2, 3, 4, 5};
- vec.erase(vec.begin() + 1, vec.begin() + 4); // 删除 2, 3, 4
- // 结果为 vec = {1, 5}
复制代码 4.4 按值删除(配合 remove)
- #include <algorithm>
- std::vector<int> vec = {1, 2, 3, 2, 4};
- // 删除所有值为 2 的元素
- vec.erase(std::remove(vec.begin(), vec.end(), 2), vec.end());
- // 结果为 vec = {1, 3, 4}
复制代码 注意:std::remove 不是真正删除,而是将不符合条件的元素移到后面,返回“新逻辑末尾”,再用 erase 删除尾部的冗余数据。
4.5 按条件删除(用 lambda)
- // 删除所有大于3的元素
- vec.erase(std::remove_if(vec.begin(), vec.end(), [](int x) {
- return x > 3;
- }), vec.end());
复制代码 4.6 清空整个 vector:clear()
- vec.clear(); // 删除所有元素,size() 为 0
复制代码 4.7 删除自定义类型的元素(按值或条件)
- struct Person {
- std::string name;
- int age;
- };
- std::vector<Person> people = {
- {"Alice", 25}, {"Bob", 30}, {"Charlie", 25}
- };
- // 删除所有 age 为 25 的人
- people.erase(std::remove_if(people.begin(), people.end(), [](const Person& p) {
- return p.age == 25;
- }), people.end());
复制代码 4.8 删除某个元素再次遍历
方法 1:使用 erase + iterator,精确方式如下:
- #include <vector>
- #include <iostream>
- int main() {
- std::vector<int> vec = {1, 2, 3, 2, 4};
- for (auto it = vec.begin(); it != vec.end(); ) {
- if (*it == 2) {
- it = vec.erase(it); // erase 返回新的 iterator,指向被删元素的下一个位置
- } else {
- ++it;
- }
- }
- // 再次遍历
- for (int val : vec) {
- std::cout << val << " ";
- }
- return 0;
- }
复制代码 方法 2:先删除,再单独遍历(更清晰):
- vec.erase(std::remove(vec.begin(), vec.end(), 2), vec.end());
- // 再次遍历
- for (int val : vec) {
- std::cout << val << " ";
- }
复制代码 错误示例(不要这样做):
- for (auto it = vec.begin(); it != vec.end(); ++it) {
- if (*it == 2) {
- vec.erase(it); // ❌ it 会失效,下一次 ++it 就是未定义行为
- }
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |