C++第九讲:vector
C第九讲vectorvector 是STL 中最常用的序列式容器本质是一个动态数组彻底解决了 C 语言静态数组大小固定、手动管理内存的痛点。它支持随机访问、自动扩容是所有 C 开发者日常开发的首选容器也是面试第一高频考点。一、vector 简介1. 什么是 vectorvector 是 C 标准库提供的动态数组容器可以存储任意类型的元素底层是一段连续的内存空间。自动管理内存不需要手动申请 / 释放空间支持随机访问通过[]像数组一样访问元素时间复杂度 O (1)自动扩容当空间不足时自动申请更大的空间并拷贝元素丰富的接口提供了增删查改等常用操作2. 为什么不用 C 语言数组对比项C 语言静态数组C 语言动态数组C vector大小编译时固定不能改变运行时可改但手动管理自动扩容无需手动管理内存管理栈上自动释放堆上手动 malloc/free自动申请释放无内存泄漏越界检查无越界可能崩溃无部分编译器支持越界检查接口无需要自己实现无提供丰富的增删查改接口二、vector 常用接口重点使用 vector 需要包含头文件#include vector所有接口都在std命名空间中。1. 构造函数4 个最常用构造函数功能说明示例vectorT()无参构造创建空 vectorvectorint v1;vectorT(size_t n, const T val T())构造 n 个值为 val 的元素vectorint v2(5, 10); // 5个10vectorT(const vectorT v)拷贝构造vectorint v3(v2);vectorT(InputIterator first, InputIterator last)用迭代器区间构造vectorint v4(v2.begin(), v2.end());代码示例#include iostream #include vector using namespace std; ​ int main() { vectorint v1; // 空vector vectorint v2(5, 10); // 5个10 vectorint v3(v2); // 拷贝v2 vectorint v4(v2.begin(), v2.begin()3); // 前3个元素10,10,10 ​ // 用数组构造 int arr[] {1,2,3,4,5}; vectorint v5(arr, arrsizeof(arr)/sizeof(int)); ​ return 0; }2. 容量操作面试高频函数功能说明注意事项size_t size() const返回有效元素个数size_t capacity() const返回总容量能存多少元素容量≥sizebool empty() const判断是否为空空返回 truevoid reserve(size_t n)预留 n 个元素的空间✅ 只改容量不改 size提前预留避免频繁扩容void resize(size_t n, const T val T())把有效元素改为 n 个nsize用 val 填充nsize截断可能改变容量核心考点vector 的扩容机制当 vector 的 size 达到 capacity 时再插入元素会触发自动扩容申请一块更大的新空间VS 按1.5 倍扩容G 按2 倍扩容将旧空间的元素拷贝到新空间释放旧空间更新指针指向新空间代码验证扩容倍数void TestExpand() { vectorint v; size_t sz v.capacity(); cout 初始容量 sz endl; for (int i0; i100; i) { v.push_back(i); if (sz ! v.capacity()) { sz v.capacity(); cout 扩容到 sz endl; } } }VS 输出1→2→3→4→6→9→13→19→28→42→63→94→1411.5 倍G 输出1→2→4→8→16→32→64→1282 倍优化技巧提前 reserve 预留空间如果知道大概要存储多少元素提前用reserve预留空间避免频繁扩容扩容会拷贝元素效率低vectorint v; v.reserve(100); // 提前预留100个元素空间 for (int i0; i100; i) { v.push_back(i); // 不会触发扩容 }3. 增删查改操作函数功能说明时间复杂度void push_back(const T val)尾插元素O (1)扩容时 O (n)void pop_back()尾删元素O(1)iterator insert(iterator pos, const T val)在 pos 位置插入 valO (n)需要搬移元素iterator erase(iterator pos)删除 pos 位置的元素O (n)需要搬移元素void swap(vectorT v)交换两个 vector 的底层空间O (1)只交换指针T operator[](size_t pos)访问 pos 位置的元素O(1)注意find 不是 vector 的成员函数查找元素需要使用algorithm头文件中的find算法#include algorithm vectorint v {1,2,3,4,5}; // 查找3返回迭代器找不到返回v.end() auto it find(v.begin(), v.end(), 3); if (it ! v.end()) { cout 找到了 *it endl; }4. 迭代器vector 的迭代器本质是原生指针支持 、--、*、- 等操作。迭代器功能说明begin()/end()正向迭代器begin 指向第一个元素end 指向最后一个元素的下一个位置rbegin()/rend()反向迭代器rbegin 指向最后一个元素rend 指向第一个元素的前一个位置cbegin()/cend()const 正向迭代器只读代码示例三种遍历方式int main() { vectorint v {1,2,3,4,5}; ​ // 1. []访问推荐最简洁 for (int i0; iv.size(); i) { cout v[i] ; } cout endl; ​ // 2. 迭代器 vectorint::iterator it v.begin(); while (it ! v.end()) { cout *it ; it; } cout endl; ​ // 3. 范围forC11推荐 for (auto e : v) { cout e ; } cout endl; ​ return 0; }三、核心难点迭代器失效面试必考1. 什么是迭代器失效vector 的迭代器本质是指向底层数组的指针当底层空间被释放或元素位置发生改变时原来的迭代器就会变成野指针继续使用会导致程序崩溃或结果错误。2. 两种导致迭代器失效的场景场景 1底层空间改变扩容所有会导致扩容的操作都会使迭代器失效reserve、resize、insert、push_back、assign等。错误示例int main() { vectorint v {1,2,3,4,5}; auto it v.begin(); cout 扩容前容量 v.capacity() endl; // 5 ​ // 触发扩容旧空间被释放it变成野指针 v.reserve(100); cout 扩容后容量 v.capacity() endl; // 100 ​ // 错误使用失效的迭代器VS下直接崩溃G下结果错误 while (it ! v.end()) { cout *it ; it; } return 0; }场景 2指定位置删除元素erase删除 pos 位置的元素后pos 后面的元素会往前搬移导致pos 及之后的迭代器失效VS 下严格检测G 下部分情况可能运行但结果错误。错误示例删除所有偶数// 错误写法 int main() { vectorint v {1,2,3,4}; auto it v.begin(); while (it ! v.end()) { if (*it % 2 0) { v.erase(it); // 删除后it失效 } it; // 访问失效的迭代器崩溃 } return 0; }正确写法erase会返回删除元素的下一个位置的迭代器用这个返回值更新 it// 正确写法 int main() { vectorint v {1,2,3,4}; auto it v.begin(); while (it ! v.end()) { if (*it % 2 0) { it v.erase(it); // 用返回值更新it } else { it; } } return 0; }3. 迭代器失效的解决方法所有可能导致迭代器失效的操作后重新获取迭代器。扩容后重新调用begin()获取新的迭代器erase 后使用erase返回的迭代器四、vector 底层原理与模拟实现1. 底层结构vector 的底层非常简单只有三个指针_start指向数组的起始位置_finish指向最后一个有效元素的下一个位置_endofstorage指向数组容量的末尾位置templateclass T class vector { private: T* _start; T* _finish; T* _endofstorage; };核心关系size() _finish - _startcapacity() _endofstorage - _start2. 模拟实现核心函数2.1 构造与析构templateclass T class vector { public: // 无参构造 vector() : _start(nullptr) , _finish(nullptr) , _endofstorage(nullptr) {} // 构造n个val vector(size_t n, const T val T()) : _start(nullptr) , _finish(nullptr) , _endofstorage(nullptr) { reserve(n); for (size_t i0; in; i) { push_back(val); } } // 拷贝构造深拷贝 vector(const vectorT v) : _start(nullptr) , _finish(nullptr) , _endofstorage(nullptr) { reserve(v.capacity()); for (const auto e : v) { push_back(e); } } // 赋值运算符重载现代版 vectorT operator(vectorT v) { swap(v); return *this; } // 析构函数 ~vector() { if (_start) { delete[] _start; _start _finish _endofstorage nullptr; } } // 交换两个vector void swap(vectorT v) { std::swap(_start, v._start); std::swap(_finish, v._finish); std::swap(_endofstorage, v._endofstorage); } // ... 其他成员函数 private: T* _start; T* _finish; T* _endofstorage; };2.2 容量操作reservevoid reserve(size_t n) { if (n capacity()) { size_t oldSize size(); // 1. 申请新空间 T* tmp new T[n]; // 2. 拷贝元素不能用memcpy自定义类型会浅拷贝 for (size_t i0; ioldSize; i) { tmp[i] _start[i]; } // 3. 释放旧空间 delete[] _start; // 4. 更新指针 _start tmp; _finish _start oldSize; _endofstorage _start n; } }易错点不能用 memcpy 拷贝自定义类型memcpy 是浅拷贝如果 vector 存储的是 string、vector 等自定义类型memcpy 会导致多个对象共享同一块内存析构时重复释放崩溃。必须用赋值运算符进行深拷贝。2.3 尾插push_backvoid push_back(const T val) { // 空间满了就扩容 if (_finish _endofstorage) { size_t newCapacity capacity() 0 ? 4 : capacity() * 2; reserve(newCapacity); } // 尾插元素 *_finish val; _finish; }2.4 访问与迭代器T operator[](size_t pos) { assert(pos size()); return _start[pos]; } const T operator[](size_t pos) const { assert(pos size()); return _start[pos]; } iterator begin() { return _start; } iterator end() { return _finish; }五、动态二维数组vectorvectorTvector 可以嵌套使用实现动态二维数组比 C 语言的二维数组更灵活。1. 原理vectorvectorint vv(n)表示一个包含 n 个vectorint的 vector每个元素都是一个独立的 vector。2. 示例杨辉三角class Solution { public: vectorvectorint generate(int numRows) { // 创建numRows行的二维数组 vectorvectorint vv(numRows); // 每行的元素个数等于行号1初始化为1 for (int i0; inumRows; i) { vv[i].resize(i1, 1); } // 填充中间元素第i行第j列 第i-1行第j列 第i-1行第j-1列 for (int i2; inumRows; i) { for (int j1; ji; j) { vv[i][j] vv[i-1][j] vv[i-1][j-1]; } } return vv; } };六、经典 OJ 实战1. 只出现一次的数字// 要求线性时间复杂度不使用额外空间 class Solution { public: int singleNumber(vectorint nums) { int res 0; for (int e : nums) { res ^ e; // 异或相同为0不同为1 } return res; } };2. 删除排序数组中的重复项// 要求原地修改空间复杂度O(1) class Solution { public: int removeDuplicates(vectorint nums) { if (nums.empty()) return 0; int slow 0; for (int fast1; fastnums.size(); fast) { if (nums[fast] ! nums[slow]) { nums[slow] nums[fast]; } } return slow 1; } };七、本章核心总结vector 是动态数组底层是连续内存支持随机访问自动扩容扩容机制VS1.5 倍G2 倍提前 reserve 可优化性能迭代器失效扩容和 erase 会导致失效解决方法是操作后重新获取迭代器模拟实现核心是三个指针深拷贝避免浅拷贝问题不能用 memcpy 拷贝自定义类型常用接口push_back、pop_back、operator []、reserve、resize、迭代器

相关新闻

操作系统EAL4+认证的范围界定与实战策略

操作系统EAL4+认证的范围界定与实战策略

1. 操作系统EAL4认证的核心挑战与范围界定价值 在信息技术安全领域,EAL4认证是Common Criteria(通用准则)评估体系中公认的"高保障级"门槛。我参与过三个操作系统内核的认证项目,深刻体会到范围界定(Scope D…

2026/9/28 23:06:41 阅读更多 →
如何在Zotero 7+中高效管理插件:智能插件市场全面指南

如何在Zotero 7+中高效管理插件:智能插件市场全面指南

如何在Zotero 7中高效管理插件:智能插件市场全面指南 【免费下载链接】zotero-addons Zotero Add-on Market | Zotero插件市场 | Browsing and installing plugins within Zotero 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-addons Zotero插件市场…

2026/9/29 0:24:22 阅读更多 →
福州看诊多动症注意力问题哪家医院靠谱

福州看诊多动症注意力问题哪家医院靠谱

不少福州学龄儿童家长都有类似的困惑:孩子上课坐不住、写作业磨磨蹭蹭,到底是天性好动还是多动症?就诊时怎么选专业机构才能少走弯路?近年来公众对注意缺陷多动障碍(俗称多动症)的认知度不断提升&#xff0…

2026/10/3 15:24:41 阅读更多 →

最新新闻

NSST图像融合实战:从NSCT迁移到剪切波工具箱的完整指南

NSST图像融合实战:从NSCT迁移到剪切波工具箱的完整指南

简介:NSST工具箱是一套面向图像融合研究的MATLAB实现,全称非下采样剪切波变换工具箱,适合从事遥感图像处理、医学影像分析及多源图像融合的科研人员与工程师使用。它针对传统PCA、小波、DCT等方法在边缘与细节保持上的不足,利用非…

2026/10/9 12:08:16 阅读更多 →
旋转编码器表面缺陷检测的机器视觉方案:从硬件选型到形态学算法落地

旋转编码器表面缺陷检测的机器视觉方案:从硬件选型到形态学算法落地

简介:一套基于机器视觉的旋转编码器缺陷检测系统完整代码与实验样本,面向伺服电机生产线质检工程师、机器视觉初学者及智能制造相关专业学生,解决旋转编码器表面断裂、孔洞、凸起等缺陷的人工检测效率低、易疲劳、标准不一致等实际问题。系统…

2026/10/9 12:08:16 阅读更多 →
MATLAB中DNG材料与3D FDTD仿真的数据-模型-求解器对齐

MATLAB中DNG材料与3D FDTD仿真的数据-模型-求解器对齐

简介:本资源是一个基于MATLAB实现的三维时域有限差分法(3D FDTD)电磁仿真程序,面向电磁场与微波技术方向的本科生、研究生及科研初学者,用于学习和验证电磁波在三维空间中的传播、散射与边界响应等核心问题。程序聚焦D…

2026/10/9 12:08:16 阅读更多 →
Claude超简单安装方式,三步搞定:用TaoToken统一Key跑通Node环境

Claude超简单安装方式,三步搞定:用TaoToken统一Key跑通Node环境

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 12:08:16 阅读更多 →
【粉丝福利社】高效课题申报:AI全流程智能辅助

【粉丝福利社】高效课题申报:AI全流程智能辅助

💎【行业认证权威头衔】 ✔ 华为云天团核心成员:特约编辑/云享专家/开发者专家/产品云测专家 ✔ 开发者社区全满贯:CSDN博客&商业化双料专家/阿里云签约作者/腾讯云内容共创官/掘金&亚马逊&51CTO顶级博主 ✔ 技术生态共建先锋&am…

2026/10/9 12:08:16 阅读更多 →
micro:bit硬件入门:教育级开发板原理与实战指南

micro:bit硬件入门:教育级开发板原理与实战指南

1. 项目概述:这不是一块“玩具板”,而是一把打开数字世界大门的实体钥匙micro:bit 这个名字听起来有点拗口,但如果你在小学信息课、青少年创客营或者社区科技开放日里见过它——那块比信用卡略小、正面嵌着25颗可编程LED灯、背面焊着加速度计…

2026/10/9 12:07:15 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →