当前位置: 首页 > ai >正文

【C++】 Vector容器操作全解析

C++ Vector 容器详解

1. 容量与大小管理

1.1 基本容量操作

  • size():返回当前元素个数

  • capacity():返回当前分配的内存容量(可容纳的元素数)

  • empty():判断容器是否为空

1.2 容量调整操作

  • resize(n):改变 size

    • 若 n > size,新增元素默认初始化(对于基本类型为0,类类型调用默认构造函数)

    • 若 n < size,删除尾部多余元素

    • 可选第二参数指定初始化值:resize(n, value)

  • reserve(n):改变 capacity

    • 只开空间,不初始化,不影响 size

    • 如果 n < capacity,通常无效果(实现可能忽略)

    • 如果 n > capacity,重新分配内存,可能导致迭代器失效

2. Vector 的扩容机制

2.1 不同编译器的增长策略

  • VS (PJ STL):1.5 倍增长

  • g++ (SGI STL):2 倍增长

  • Clang (通常):2 倍增长

2.2 扩容性能分析

  • 摊销常数时间:虽然单次扩容可能耗时,但多次操作的均摊时间复杂度为 O(1)

  • 扩容代价:需要分配新内存、拷贝元素、释放旧内存

  • reserve 只负责开辟空间,如果确定知道需要用多少空间,reserve 可以缓解 vector 增容的代价缺陷问题。

  • resize 在开空间的同时还会进行初始化,影响 size。

// 测试vector的默认扩容机制 
void TestVectorExpand() 
{ size_t sz;  vector<int> v;  sz = v.capacity();  cout << "making v grow:\n";  for (int i = 0; i < 100; ++i)  {  v.push_back(i);  if (sz != v.capacity())  {  sz = v.capacity();  cout << "capacity changed: " << sz << '\n'; } } 
}

// 如果已经确定vector中要存储元素大概个数,可以提前将空间设置足够 
// 就可以避免边插入边扩容导致效率低下的问题了 
void TestVectorExpandOP() 
{  vector<int> v;  size_t sz = v.capacity();  v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容  cout << "making bar grow:\n";  for (int i = 0; i < 100; ++i)  {  v.push_back(i);  if (sz != v.capacity()) {  sz = v.capacity();  cout << "capacity changed: " << sz << '\n'; } } 
}

1.2.4vector 增删查改

push_back(val):尾部插入(拷贝或移动)

pop_back():尾部删除(不返回被删除元素)

emplace_back(args...)(C++11):直接在尾部构造元素,避免拷贝

emplace(pos, args...)(C++11):在指定位置直接构造元素

find 查找(注意这个是算法模块实现,不是 vector 的成员接口)

insert 在 position 之前插入 val

erase 删除 position 位置的数据

swap 交换两个 vector 的数据空间

operator[] (重点) 像数组一样访问

4.2 插入操作详解

vector<int> v = {1, 3, 4};// 插入单个元素
v.insert(v.begin() + 1, 2); // v = {1, 2, 3, 4}// 插入多个相同元素
v.insert(v.end(), 3, 5); // v = {1, 2, 3, 4, 5, 5, 5}// 插入范围
vector<int> other = {6, 7, 8};
v.insert(v.end(), other.begin(), other.end()); // v = {1, 2, 3, 4, 5, 5, 5, 6, 7, 8}// 使用初始化列表插入(C++11)
v.insert(v.begin(), {0, -1}); // v = {-1, 0, 1, 2, 3, 4, 5, 5, 5, 6, 7, 8}

4.3 删除操作详解

vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};// 删除单个元素
v.erase(v.begin()); // 删除第一个元素// 删除范围
v.erase(v.begin() + 2, v.begin() + 4); // 删除第3和第4个元素// 删除所有元素
v.clear();// 删除满足条件的元素(使用erase-remove惯用法)
vector<int> v2 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
v2.erase(remove_if(v2.begin(), v2.end(), [](int x) { return x % 2 == 0; }), v2.end());
// 删除所有偶数

4.4 查找操作扩展

#include <algorithm>
#include <vector>vector<int> v = {1, 2, 3, 4, 5, 3, 2, 1};// 查找第一个匹配元素
auto it = find(v.begin(), v.end(), 3);
if (it != v.end()) {cout << "Found at position: " << distance(v.begin(), it) << endl;
}// 查找最后一个匹配元素
auto rit = find(v.rbegin(), v.rend(), 3);
if (rit != v.rend()) {cout << "Last found at position: " << distance(v.begin(), rit.base()) - 1 << endl;
}// 查找第一个满足条件的元素
auto it2 = find_if(v.begin(), v.end(), [](int x) { return x > 3; });// 查找子序列
vector<int> sub = {3, 4};
auto it3 = search(v.begin(), v.end(), sub.begin(), sub.end());

Lambda 表达式

[capture](parameters) -> return_type { function_body }

具体分解

  • []: 捕获列表(空,表示不捕获任何外部变量)

  • (int x): 参数列表(接受一个整数参数 x)

  • { return x > 3; }: 函数体(返回 x > 3 的比较结果)

Lambda 表达式的特性

  1. 匿名函数:没有函数名,直接定义和使用

  2. 类型推导:编译器自动推导返回类型(这里返回 bool

  3. 捕获能力:可以通过捕获列表访问外部变量(这里没有使用)

等价函数

这个 lambda 表达式等价于以下传统函数:

bool greater_than_three(int x) {return x > 3;
}

Lambda 表达式的更多用法

捕获外部变量

int threshold = 3;
// 通过值捕获外部变量
auto it = find_if(v.begin(), v.end(), [threshold](int x) { return x > threshold; });// 通过引用捕获外部变量
auto it = find_if(v.begin(), v.end(), [&threshold](int x) { return x > threshold; });

指定返回类型

// 显式指定返回类型
auto it = find_if(v.begin(), v.end(), [](int x) -> bool { return x > 3; });

复杂逻辑

// 多个条件的lambda
auto it = find_if(v.begin(), v.end(), [](int x) { return x > 3 && x % 2 == 0; // 大于3的偶数
});

4.5 访问操作扩展

vector<int> v = {1, 2, 3, 4, 5};// 使用operator[](不检查边界)
int a = v[2]; // a = 3// 使用at()(检查边界)
try {int b = v.at(10); // 抛出std::out_of_range异常
} catch (const out_of_range& e) {cout << "Out of range: " << e.what() << endl;
}// 访问首尾元素
int first = v.front(); // 等同于v[0]
int last = v.back();   // 等同于v[v.size()-1]// 直接访问底层数据
int* data = v.data(); // 获取指向底层数组的指针

标准库算法 std::find 的返回值是迭代器:

C++ 标准库的算法(如 findsort 等)是通用的,可以适配各种容器(vectorlistset 等)。

  • 迭代器为不同容器提供了统一的访问接口:无论容器内部存储结构如何(数组、链表等),算法都能通过迭代器遍历和操作元素。

  • 若不使用迭代器,find 函数需要为每种容器单独实现(如 vector 用索引,list 用指针等),违背了代码复用的原则。

http://www.xdnf.cn/news/19406.html

相关文章:

  • OpenHarmony智能语音框架深度拆解:从VAD到唤醒词打造你的AI语音智能体
  • 第8篇c++Expression: (L“Buffer is too small“ 0
  • 20.30 QLoRA微调终极指南:Hugging Face参数优化实战,24GB显存直降50%性能不减
  • 【JavaScript】async/await 与 Fetch 传参,PUT,PATCH,文件上传,批量删除等前端案例
  • 二、Git基础命令速查表
  • Goframe 框架下HTTP反向代理并支持MCP所需的SSE协议的实现
  • leetcode算法刷题的第二十三天
  • Windows Qt5.15.17源码使用VS2019编译安装
  • Linux自动化构建工具-make/Makefile
  • C#/.NET/.NET Core技术前沿周刊 | 第 52 期(2025年8.25-8.31)
  • 【论文精读】基于YOLOv3算法的高速公路火灾检测
  • Jenkins 自动构建Vue 项目的一个大坑
  • 计算机毕设选题:基于Python+Django的健康饮食管理系统设计【源码+文档+调试】
  • 【LeetCode 155】—最小栈 - 详解与实现
  • Apache Commons ConvertUtils
  • 电科金仓 KFS 场景化实践路径解析:从行业场景落地看技术价值转化
  • Redis面试重点-2
  • std::thread详解
  • JDK14安装步骤及下载(附小白详细教程)
  • 在Unity中,让子物体不随父物体移动或转动的方法!
  • 数据库索引abc,请问查询哪些字段能命中索引
  • APB验证VIP Agent的各个组件之间的通信
  • 【C++ 】string类:深拷贝与浅拷贝解析
  • ​​告别通用模型局限:5步微调实战指南​
  • 数值分析——非线性方程与方程组的数值解法之迭代法
  • [灵动微电子 MM32BIN560CN MM32SPIN0280]读懂电机MCU 模拟输入运放放大
  • NCCL-TEST ib集群测试UCX代替方案
  • unity tilemap grid 的中心轴
  • Linux中卸载和安装Nginx
  • Python爬虫实战:研究Figures与 Axes,构建社交平台具有决策价值的数据采集和分析系统