🔗 运行环境:C/C++
🚩 撰写作者:左手の明天
🥇 精选专栏:《python》
🔥 推荐专栏:《算法研究》
🔐#### 防伪水印——左手の明天 ####🔐
💗 大家好🤗🤗🤗,我是左手の明天!好久不见💗
💗今天分享【C/C++】——vector的增删改查操作💗
📆 最近更新:2025 年 02 月 15 日,左手の明天的第 350 篇原创博客
📚 更新于专栏:C/C++入门与进阶
🔐#### 防伪水印——左手の明天 ####🔐
一、Vector容器概述
Vector是C++标准模板库(STL)中最常用的序列式容器,本质上是一个动态数组。与静态数组相比,vector具有以下核心优势:
-
动态扩容:自动管理内存空间,容量随元素增加自动扩展
-
类型安全:强类型约束保证数据一致性
-
丰富接口:提供超过30种成员函数方便操作
-
迭代器支持:兼容STL算法和泛型编程
二、基础操作快速入门
1. 包含头文件
首先,确保你的代码中包含了vector
的头文件:
#include <vector>
2. 容器创建与初始化
// 创建空vector
vector<int> v1;// 指定初始容量
vector<string> v2(10); // 初始化列表(C++11)
vector<char> vowels {'a', 'e', 'i', 'o', 'u'};// 拷贝构造
vector<float> v3(v2);
还可以使用不同的方式来初始化vector
:
std::vector<int> vec1; // 默认初始化,创建一个空的vectorstd::vector<int> vec2(10); // 创建一个包含10个默认值(0)的vectorstd::vector<int> vec3(10, 1); // 创建一个包含10个值1的vectorstd::vector<int> vec4 = {1, 2, 3, 4, 5}; // 使用初始化列表初始化vector
3. 元素访问操作
vector<double> prices {19.99, 9.99, 15.49};// 下标访问(不检查越界)
cout << prices[0]; // 19.99// at()方法(边界检查)
cout << prices.at(1); // 9.99// 首尾元素访问
cout << prices.front(); // 19.99
cout << prices.back(); // 15.49
三、核心操作深度解析
1. 元素添加操作
vector<int> nums;// 尾部追加
nums.push_back(10); // [10]// 批量插入
nums.insert(nums.end(), {20, 30}); // [10,20,30]// 指定位置插入
auto it = nums.begin() + 1;
nums.insert(it, 15); // [10,15,20,30]// 高效构造(C++11)
nums.emplace_back(40); // 避免临时对象拷贝
2. 元素删除操作
-
删除末尾元素:使用
pop_back()
方法。 -
删除指定位置的元素:可以使用
erase()
方法。
vec1.pop_back(); // 删除vec1的最后一个元素
vec1.erase(vec1.begin() + 2); // 删除vec1中索引为2的元素(注意索引从0开始)
vector<string> names {"Alice", "Bob", "Charlie"};// 移除末尾元素
names.pop_back(); // 移除"Charlie"// 删除指定位置
names.erase(names.begin()); // 删除"Alice"// 范围删除
names.erase(names.begin()+1, names.end()); // 清空容器
names.clear();
3. 数据修改操作
直接通过索引访问并修改元素:
vec1[2] = 20; // 将vec1中索引为2的元素修改为20
vector<int> data {1,2,3,4};// 直接修改元素
data[1] = 20; // [1,20,3,4]// 使用迭代器修改
auto it = data.begin() + 2;
*it = 30; // [1,20,30,4]// 范围替换
vector<int> newData {5,6,7};
data.swap(newData); // data现在为[5,6,7]
4. 数据查询操作
(1)通过索引访问元素:
int value = vec1[2]; // 获取vec1中索引为2的元素的值
(2)使用find()
方法,注意find()
返回的是一个迭代器:
vector<string> colors {"red", "green", "blue"};// 遍历查询
for(const auto& color : colors) {if(color == "green") {cout << "Found green";}
}// 使用find算法
auto pos = find(colors.begin(), colors.end(), "blue");
if(pos != colors.end()) {cout << "Index: " << pos - colors.begin();
}
5. 获取大小和容量
-
大小:已存储的元素数量。
-
容量:在不重新分配内存的情况下,容器能保存的元素的最大数量。
std::cout << "Size: " << vec1.size() << std::endl; // 输出vec1的大小(已存储的元素数量)std::cout << "Capacity: " << vec1.capacity() << std::endl; // 输出vec1的容量(最大存储能力)
四、性能优化与最佳实践
1. 容量管理
vector<int> vec;
vec.reserve(1000); // 预分配空间,避免多次扩容
2. 高效插入
// 批量插入比单次插入更高效
vector<int> source {1,2,3};
vec.insert(vec.end(), source.begin(), source.end());
3. 删除优化
// 高效移除特定元素(删除所有奇数)
vec.erase(remove_if(vec.begin(), vec.end(), [](int x){return x%2 !=0;}), vec.end());
五、典型应用场景
-
动态数据集处理(实时数据流)
-
需要随机访问的集合操作
-
替代传统数组的现代化方案
-
算法实现中的临时容器
六、注意事项
1. 迭代器失效问题
-
插入操作可能导致所有迭代器失效
-
删除操作会使被删元素之后的迭代器失效
2. 复杂度分析
-
随机访问:O(1)
-
尾部操作:O(1)
-
中间插入/删除:O(n)
3. 容器选择建议
-
频繁头部操作:考虑deque
deque的定义和特性
deque(双端队列)是C++标准模板库(STL)中的一种数据结构,允许在两端进行插入和删除操作。deque是基于动态数组实现的,与vector类似,但deque在两端操作上有更好的性能。其特点包括:
- 高效的两端操作:deque可以在头部和尾部以O(1)的时间复杂度进行插入和删除操作。
- 非连续存储:与vector不同,deque的元素不一定在内存中连续存储,这使得在序列中间插入或删除元素时更加高效。
与其他数据结构的比较
- 与vector的比较:虽然deque和vector都使用动态数组实现,但deque允许在两端高效地进行插入和删除操作,而vector只能在尾部高效地进行这些操作。此外,deque的元素不一定连续存储,这使其在序列中间操作时更灵活。
- 与list的比较:list是一个双向链表,支持在任意位置的快速插入和删除操作,但其随机访问效率较低。deque在频繁的头部操作上比list更优,但在遍历效率上不如list。
使用场景
deque常用于需要频繁在头部和尾部进行操作的场景,如实现栈和队列的底层结构。由于其高效的头部和尾部操作特性,deque在需要快速入栈和出栈的操作中表现优异。
-
大量插入删除:考虑list
七、进阶技巧
-
内存分配策略:capacity()和size()的差异
-
移动语义优化(C++11)
-
自定义分配器使用
-
多维vector应用
vector<vector<int>> matrix(5, vector<int>(5)); // 5x5矩阵
总结
Vector作为C++中最核心的容器之一,其灵活性和易用性使其成为开发者的首选容器。通过合理使用增删改查接口,结合性能优化技巧,可以充分发挥vector的优势。建议在实际开发中根据具体需求选择合适的容器,对于需要频繁在中间位置进行插入删除操作的场景,可考虑改用list或deque等其他容器。