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

vector动态数组

动态数组就是由用户申请的一块连续的动态内存,封装了相关的操作接口之后就成了vector。

1、vector 动态数组 和 静态数组的区别?

维度

静态数组(C-style / std::array)

动态数组(std::vector)

内存位置

栈(或全局区)

大小

编译期固定

运行期动态增长

扩容

不支持

自动扩容(2倍或1.5倍)

底层

连续内存块

连续内存块 + 三个指针

核心共性:两者都是连续内存,支持 O(1) 随机访问。

2、 vector 的三指针模型?
┌─────────────────────────────────────────┐ │ _M_start → 指向首元素 │ │ _M_finish → 指向最后一个元素的下一个位置 │ │ _M_end_of_storage → 指向分配内存的末尾 │ └─────────────────────────────────────────┘ [a][b][c][d][ ][ ][ ][ ] ↑ ↑ ↑ start finish end_of_storage size=4 capacity=8
3、vector的扩容机制?

当调用push_back 函数插入元素,vector内存空间不足时,引发扩容机制。

(1)申请新的内存空间(一般是原内存空间的2倍,VS是1.5倍)。

(2)将原内存空间内的数据拷贝到新的内存空间。

(3)释放旧内存空间。

// 当 size == capacity,再 push_back 时: void push_back(const T& val) { if (finish != end_of_storage) { // 有空间,直接构造 construct(finish, val); ++finish; } else { // 没空间 → 扩容 size_t new_capacity = (capacity() == 0) ? 1 : capacity() * 2; // GCC: 2倍; VS: 1.5倍 T* new_start = allocate(new_capacity); // 把旧元素搬过去(浅拷贝 or 移动构造) for (size_t i = 0; i < size(); ++i) { new_start[i] = std::move(old_start[i]); } deallocate(old_start); // 释放旧内存 // 更新三个指针 } }

扩容时,所有指向元素的迭代器、指针和引用确实会全部失效。扩容时vector会申请一块更大的新内存,将原有元素拷贝或移动到新内存中,然后释放旧内存。任何指向旧内存的“地址”都成了悬垂指针,继续使用将导致未定义行为。即使没有触发扩容push_back等操作也会使end()迭代器失效。例如:

std::vector<int> v; v.reserve(10); // 预留空间,capacity = 10 auto it = v.end(); // 指向末尾(此时末尾是begin) v.push_back(1); // 未扩容,size 从 0 变 1 // it 仍然指向“末尾”,但现在末尾已经变成元素1之后了 // 实际上 it 已失效,不能再用它去访问元素1
4、vector 的 push_back 和 emplace_back 区别?
v.push_back(MyClass(1, 2)); // 构造临时对象 → 拷贝/移动进 vector v.emplace_back(1, 2); // 直接在 vector 内存里构造,零拷贝

push_back()它会先创建一个临时 MyClass 对象(在栈上或寄存器中)。 然后将这个临时对象移动或拷贝到 vector 中(默认会先进行移动,对象不支持移动构造时触发拷贝,如果连拷贝构造也不支持,那么就会编译失败)。

5、vector 扩容后迭代器为什么失效?

扩容会重新分配内存并把旧内存的元素搬过去,旧内存被释放。原来指向旧地址的迭代器/指针就变成了悬空指针,访问会产生未定义行为报错。

vector<int> v = {1, 2, 3}; auto it = v.begin(); v.push_back(4); // 可能扩容 // it 此时已失效!不能再使用
6、reserve 和 resize 的区别?

reserve(n)

resize(n)

改变 size

❌ 不改变

✅ 改变

改变 capacity

✅ 可能增大

✅ 可能增大

构造元素

❌ 不构造

✅ 构造 n 个元素

用途

预分配,避免扩容

改变实际元素个数

vector<int> v; v.reserve(100); // capacity=100, size=0, 没有元素 v.resize(100); // capacity=100, size=100, 100个0
7、vector 底层是连续内存,怎么证明?
// 1. &v[i+1] - &v[i] == 1,地址连续 // 2. vector 可以兼容 C 接口:&v[0] 或 v.data() void c_func(int* arr, size_t n); c_func(v.data(), v.size()); // 可以直接传
8、为什么 vector 的 operator[] 不检查越界,at() 会?
v[10]; // 不检查,越界 → 未定义行为,但快 v.at(10); // 抛 std::out_of_range 异常,安全

[ ] 追求零开销抽象(和 C 数组一致),at() 提供安全版本。面试时可以补充:自己写库代码用 at(),写性能敏感代码用 [ ]。

9、vector 内存什么时候释放?clear() 会释放吗?

clear() 只析构元素,不改变 capacity,内存不释放

shrink_to_fit() 请求缩减到 size(但标准说"请求",执行可能会不成功,执行原理是重新申请一块新内存,然后将旧数据拷贝过去,再)

真正释放:vector 析构时,或 vector<T>().swap(v) 这个经典技巧

http://www.jsqmd.com/news/1262858/

相关文章:

  • 黑苹果终极配置指南:从硬件兼容性到系统优化的完整解决方案
  • 3个理由告诉你:为什么SyncTrayzor是Windows上最完美的Syncthing图形界面工具
  • 实测反馈!这家轻松省心的北京旅游纯玩团公司,服务超棒值得选! - 速递信息
  • 涂胶显影机(Track)技术岗普通专家工程师完整JD(12维度)+对外简化版JD
  • 使用86Box模拟器在Windows XP SP3上实现复古计算环境搭建指南
  • 2026年屋顶隔热公司权威评测:辰稀热盾稀土纳米技术登顶TOP1榜单 - 行业评论官xj
  • 展示型网站建设价格揭秘:别被低价忽悠,7年老站长的真心话
  • 新手必看,五分钟在Taotoken平台获取API Key并完成首次模型调用
  • 私有化IM厂商排名 - IM软件测评
  • 谷歌NanoBanana 2轻量AI模型解析与边缘计算实践
  • OpenClaw自训练技术解析与应用实践
  • 上班族打车如何省钱?每天通勤都能用,轻松降低出行成本 - 工具软件使用方法推荐
  • 出差参加客户2026年度线下技术培训 新人怎么做好视频内容整理
  • 3分钟解锁Navicat Premium无限试用:macOS用户的终极重置指南
  • AI辅助留学文书写作:提升效率与质量的关键技巧
  • Phoneme-Synthesis 终极指南:3步快速实现国际音标语音合成
  • BaiduPCS-Web终极指南:如何突破百度网盘限速实现高速下载
  • 基于NVIDIA DGX Spark的VisionLink端侧视障AI项目
  • DDrawCompat:现代Windows上运行经典游戏的终极兼容性解决方案
  • 2026年上海屋顶隔热施工公司综合评测:辰稀热盾领衔节能方案推荐 - 行业评论官xj
  • 2026攀枝花CMA甲醛检测公司怎么选:只测不除的专业第三方实验室——万清测研检测及公共卫生检测 - 创达咨询
  • AI情感隔离系统:技术架构与伦理实践
  • AI编程代理实战指南:从原理到项目,掌握Claude Code高效开发
  • 前端复杂问题解决:调试技巧与思维模式
  • AM62L DEBUGSS寄存器深度解析:从身份识别到交叉触发实战
  • 如何为OpenClaw工具配置Taotoken作为其大模型供应商
  • 2026年FT排名揭晓:复旦EMBA领跑中文项目 - 新闻快传
  • 2026长春、哈尔滨、石家庄线上洗衣服务,优选优依派上门洗护 - 新闻快传
  • 标注成本直降76%,标注周期压缩至1/5,AI自动化标注真能闭环吗?
  • Rust游戏CPU虚拟化冲突解决方案:BIOS设置与Windows功能调整