C++ STL 完整入门笔记[3]:vector底层剖析 附杨辉三角实战
前言刷 LeetCode118 杨辉三角时发现很多同学只会调用vector接口完成题目却完全不懂vector底层内存模型、push_back扩容逻辑、二维vector存储结构。本文结合手写源码 杨辉三角实战彻底吃透vector底层原理。一、vector 基础用法与初始化1. 列表初始化initializer_list#include vector #include string using namespace std; // 1. 列表初始化底层依赖initializer_list vectorint v1({10, 20, 30}); vectorint v2{10, 20, 30, 1,1,1}; // 2. push_back插入临时对象 vectorstring str_v; str_v.push_back(张三); // 底层构造string临时对象拷贝/移动到vector内存底层逻辑vector接收initializer_list参数的构造函数会遍历列表循环调用push_back完成元素拷贝。2. vector 核心修改接口 Modifiers接口作用底层行为push_back(val)尾部插入元素容量充足直接构造容量不足触发扩容emplace_back(args)尾部原位构造直接在内存构造对象无临时对象效率更高insert指定位置插入后续元素全部后移时间复杂度 O (n)erase删除指定元素后续元素前移O (n)clear清空元素析构所有对象不释放底层内存pop_back删除尾部元素析构最后一个元素容量不变二、vector 底层内存模型手写简化源码1. vector 类核心成员templateclass T, class Alloc allocatorT class vector { public: typedef T value_type; typedef T* iterator; private: iterator _start; // 有效数据起始地址 iterator _finish; // 有效数据末尾下一位 iterator _end_of_storage; // 内存容量末尾 public: // 构造、析构、接口省略 iterator begin() { return _start; } iterator end() { return _finish; } // 有效元素个数 size_t size() const { return _finish - _start; } // 总容量 size_t capacity() const { return _end_of_storage - _start; } };内存图解[_start 元素1 元素2 元素3 _finish 空闲内存 _end_of_storage]size()_finish - _start当前存了多少元素capacity()_end_of_storage - _start整块内存能容纳多少元素2. push_back 扩容核心逻辑void push_back(const T x) { // 内存还有空闲直接在_finish处构造对象 if (_finish ! _end_of_storage) { construct(_finish, x); _finish; } else { // 空间不足触发扩容 insert_aux(end(), x); } }扩容流程insert_aux计算新容量原容量为 0 则扩为 1否则扩容为原来 2 倍分配一块更大的连续内存将旧内存中所有元素拷贝到新内存在新内存尾部插入待新增元素析构释放旧内存整块空间更新_start/_finish/_end_of_storage指向新内存3. emplace_back 与 push_back 区别push_back(const T val)先构造临时对象再拷贝 / 移动到 vector 内存存在临时对象开销emplace_back(参数1, 参数2...)直接在 vector 底层内存原位构造对象无临时对象性能更优4. 二维 vector 存储结构vectorvectorintvectorvectorint vv; vv.resize(numRows, vectorint());内存模型拆解外层vectorvectorint底层存一堆vectorint对象指针数组每个内层vectorint独立拥有自己的三块指针_start/_finish/_end_of_storage各自管理一维 int 数组vv[i][j]等价vv.operator[](i).operator[](j)先取第 i 个内层 vector再取它的第 j 个 int 元素三、实战LeetCode 118 杨辉三角题目要求给定非负整数numRows生成杨辉三角前numRows行每行首尾都是 1中间数字 上一行左上 右上数字。C vector 完整实现#include vector using namespace std; class Solution { public: vectorvectorint generate(int numRows) { vectorvectorint vv; // 1. 先开辟numRows行空间每行初始为空vector vv.resize(numRows, vectorint()); for (size_t i 0; i numRows; i) { // 第i行有 i1 个元素提前resize分配空间 vv[i].resize(i 1); // 每行首尾固定为1 vv[i][0] 1; vv[i][i] 1; } // 从第3行(i2)开始填充中间数值 for (size_t i 2; i vv.size(); i) { for (size_t j 1; j vv[i].size() - 1; j) { // 当前值 上一行j-1 上一行j vv[i][j] vv[i-1][j-1] vv[i-1][j]; } } return vv; } };代码思路解析外层 vector 开辟行vv.resize(numRows, vectorint())创建 numRows 个空一维 vector每行预分配列空间第i行共i1个元素vv[i].resize(i1)提前分配连续 int 内存避免多次扩容首尾赋值 1杨辉三角每行第一个、最后一个数字恒为 1递推填充中间值从第三行i2开始中间元素等于上一行相邻两数之和拓展C 语言动态二维数组实现对比 vector很多同学混淆 C 语言二级指针二维数组和 C 二维 vector附上 C 版本对比/** * Return an array of arrays of size *returnSize. * The sizes of the arrays are returned as *returnColumnSizes array. */ int** generate(int numRows, int* returnSize, int** returnColumnSizes) { // 外层指针数组存放每行int数组地址 int** aa (int**)malloc(sizeof(int*) * numRows); // 记录每行元素个数 *returnColumnSizes (int*)malloc(sizeof(int) * numRows); for (int i 0; i numRows; i) { int col i 1; aa[i] (int*)malloc(sizeof(int) * col); (*returnColumnSizes)[i] col; aa[i][0] 1; aa[i][i] 1; } for (int i 2; i numRows; i) { for (int j 1; j i; j) { aa[i][j] aa[i-1][j-1] aa[i-1][j]; } } *returnSize numRows; return aa; }C 与 C vector 核心区别C 二级指针二维数组每行 int 数组内存不连续仅外层指针连续手动 malloc 分配、free 释放容易内存泄漏Cvectorvectorint每个内层 vector 内部 int 连续vector 自动管理内存出作用域自动析构释放无需手动管理堆内存四、vector 核心知识点总结三指针模型_start/_finish/_end_of_storage区分 size 和 capacity底层是连续堆内存扩容机制空间不足默认 2 倍扩容旧内存数据拷贝后释放扩容存在性能开销大量数据建议提前reserve()预分配容量emplace_back 优于 push_back原位构造消除临时对象拷贝开销二维 vector 本质存储多个独立一维 vector 对象各行内存互不连续使用场景需要动态长度、随机访问的数组场景底层连续内存缓存友好随机访问 O (1)

相关新闻

Linux进程权限

Linux进程权限

本文是Linux系统下讨论。注意,Linux和Unix有很多不同的地方,并且各个不同的Unix系统也有很多不同。 本文讨论对象: ruid: real user id,即实际用户,也即当前登录的用户euid: effective user id, 即有效用…

2026/10/10 13:47:47 阅读更多 →
HarmonyOS ArkTS 实战:实现一个校园证件照拍摄与预约应用

HarmonyOS ArkTS 实战:实现一个校园证件照拍摄与预约应用

HarmonyOS ArkTS 实战:实现一个校园证件照拍摄与预约应用 项目效果 本文使用 HarmonyOS 和 ArkTS 实现一个校园证件照拍摄与预约应用。 应用可以预约证件照拍摄,选择证件照尺寸,在线选片,查看拍摄样片,并提供拍摄预约、照片下载、打印配送等功能。 项目使用 DevEco Studio…

2026/10/11 5:21:56 阅读更多 →
Tiva™ C系列外设管理:PP与SR寄存器实战指南

Tiva™ C系列外设管理:PP与SR寄存器实战指南

1. 从寄存器手册到实战:Tiva™ C系列外设管理的核心逻辑如果你和我一样,长期泡在嵌入式开发的一线,特别是基于ARM Cortex-M内核的MCU,那你肯定对“外设管理”这四个字深有感触。它远不止是初始化几个时钟、配置几个引脚那么简单。…

2026/10/11 11:39:23 阅读更多 →

最新新闻

牛客寒假算法集训营第一场题解:双指针、树形DP与字符串DP实战

牛客寒假算法集训营第一场题解:双指针、树形DP与字符串DP实战

牛客寒假算法基础集训营第一场这套题,我印象挺深。难度曲线并不是那种“签到题送到嘴边、压轴题劝退所有人”的极端分布,前几道确实送分,但从G题开始就进入双指针、树形DP、字符串DP这些正经考点,最后两道又考模型转化和临场取舍。…

2026/10/12 6:04:34 阅读更多 →
Codex额度总不够用?揪出4种隐蔽的无效消耗

Codex额度总不够用?揪出4种隐蔽的无效消耗

1. 额度告急的真相:先别急着升级套餐用Codex写代码的人,十个里有八个都经历过这种场景:正写到关键逻辑,突然弹出一行提示说额度用完了,只能干瞪眼等到下一个重置周期。第一反应往往是"是不是我的Plus套餐太少了&q…

2026/10/12 6:04:33 阅读更多 →
特征工程实战全流程:从原始数据到房价预测 R² 0.82 的进阶之路

特征工程实战全流程:从原始数据到房价预测 R² 0.82 的进阶之路

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

2026/10/12 6:04:33 阅读更多 →
claude-mem 记忆层实战:为 Claude 构建持久化记忆系统

claude-mem 记忆层实战:为 Claude 构建持久化记忆系统

1. 项目缘起与核心定位第一次看到 claude-mem 这个标题,我的直觉是:这应该是一个围绕 Claude 生态做“记忆层”的项目。事实也确实如此。它的核心目标很明确——给 Claude 这类大语言模型加上一层可持久化、可检索、可管理的记忆系统,让模型在…

2026/10/12 6:04:33 阅读更多 →
DeepSeek Harness局域网AI Agent平台Docker部署实战

DeepSeek Harness局域网AI Agent平台Docker部署实战

1. 为什么局域网里需要一个“能自己干活”的AI Agent平台最近两周,我帮三个不同背景的朋友搭过类似系统:一位做工业设备预测性维护的某公司工程师,想让大模型自动读取PLC日志并生成故障简报;一位高校实验室的某导师,希…

2026/10/12 6:04:33 阅读更多 →
有害气体控制洁净工程的底层逻辑:从过滤到吸附,从压差到监测

有害气体控制洁净工程的底层逻辑:从过滤到吸附,从压差到监测

空气里最危险的不是脏,而是失控:有害气体控制洁净工程的底层逻辑干了这么多年洁净工程,我越来越觉得“洁净”这个词会误导人。很多人一听到洁净室,想到的就是无尘、高等级过滤、白大褂和干干净净的地板,下意识把“颗粒…

2026/10/12 6:03:33 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练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/11 14:36:54 阅读更多 →