vector 面试点总结

news2025/4/26 2:57:49

ps:部分内容使用“AI”查询

一、入门

1、什么是vector

动态数组容器,支持自动扩容、随机访问和连续内存存储。

2、怎么创建-初始化vector

std::vector<int> v;  // 创建空vector

std::vector<int> v = {1, 2, 3};  // 直接初始化

std::vector<int> v(5, 0); // 指定大小和值(5个0)

3、访问方式

  • operator[](无边界检查): int v = vec[6];
  • at()(有边界检查): vec.at(6) = 8;

4、size()capacity()的区别?

  • size():当前元素数量。—— 实际的(比如下课时间,班里只有10个人
  • capacity():当前分配的内存可容纳的元素数量(capacity >= size)—— resize改变的是capacity(比如下课时间,班里只有10个人,但是班级里座位能容纳50个学生

5、vector 在堆上 

二、进阶

1、扩容机制

size == capacity时,容器会分配一块更大的连续内存块,新容量通常是当前容量的 ​1.5~2倍​(具体倍数因实现而异,例如 GCC 默认采用 1.5 倍,而 MSVC 常用 2 倍)。

容器将旧内存中的所有元素 ​复制​ 或 ​移动​ 到新内存中。

  • 复制:适用于不支持移动语义的类型(如 std::array)。
  • 移动:适用于支持移动语义的类型(如 std::string、自定义类),可避免深拷贝开销

释放:旧内存被释放,容器内部指针更新为新内存地址 

均摊时间复杂度push_back 的均摊时间复杂度为 ​O(1),但每次扩容操作需 O(n)时间(n 为当前元素数量)。若频繁触发扩容(如循环中不断 push_back),总时间复杂度可能退化为 ​O(n²),显著影响性能

代价: 时间复杂度O(n),可能影响性能

2、如何避免频繁扩容

使用reserve(n)预分配内存

3、迭代器失效的场景

  • vector内存布局:[1, 2, 3, 4, 5]
  • 迭代器it指向元素2
  • 元素2被删除,后续元素3,4,5前移填补空缺。vector内存布局变为:[1, 3, 4, 5]。it迭代器失效(指向原位置2,但该位置已被覆盖)。erase()返回新迭代器new_it,指向原it的下一个元素3
// 正确更新迭代器例子
it = vec.erase(it); // it 现在指向 3

插入/删除元素(尤其是非尾部操作)可能导致迭代器失效。

比如:扩容时,会导致复制​ 或 ​移动​ 内容到新内存中,同时释放原始内存,容器内部指针更新为新内存地址 。原有迭代器指向的旧内存空间被释放,导致迭代器失效。

std::vector<int> vec = {1,2,3};
auto it = vec.begin(); // 指向1
vec.insert(it, 0);     // 可能扩容,it失效

删除元素时,后续元素会向前移动填补空位,导致被删除元素及其后的迭代器失效

在中间或开头插入/删除元素时,操作点之后的所有迭代器均失效

解决方法:

  • a、重新获取迭代器或使用范围for循环
  • b、inserterase等函数返回指向新有效位置的迭代器,可直接更新迭代器
it = vec.insert(it, 0); // 插入后返回新迭代器
it = vec.erase(it);     // 删除后返回下一个有效迭代器
  • c、​范围for循环(推荐)​
// 此方法仅适用于删除第一个符合条件的元素。若需删除多个元素,必须采用其他方法(如erase-remove惯用法或反向遍历
for (auto& elem : vec) {
    if (elem % 2 == 0) {
        vec.erase(std::find(vec.begin(), vec.end(), elem));
        break; // 循环迭代器未再被使用,避免了后续可能的失效访问。
    }
}
  • d、​反向遍历:从后向前删除元素,避免影响未遍历的迭代器。
std::vector<int> vec = {1, 2, 3, 4, 5};
for (auto rit = vec.rbegin(); rit != vec.rend(); ) {
    if (*rit % 2 == 0) {
        rit = decltype(rit)(vec.erase(std::next(rit).base()));
    } else {
        ++rit;
    }
}
// 反向迭代器遍历:通过rbegin()和rend()获取反向迭代器范围,实现从末尾向开头的遍历
// std::next(it).base()将反向迭代器转换为对应的正向迭代器(指向当前元素的前一个元素)
// 调用vec.erase()删除该元素,并返回下一个有效正向迭代器

反向迭代器rit初始化为vec.rbegin()(指向5) 

rit指向4(偶数),执行vec.erase(std::next(rit).base())

4被删除,5前移填补空缺

rit更新为vec.rend()(循环结束)

  • e、 erase-remove

 std::remove将待删除元素移到容器末尾,并返回新逻辑末尾的迭代器;erase根据该迭代器真正删除元素。
remove_if标记待删除元素,将不需要删除的元素移到vector前端,返回“新逻辑末尾”迭代器new_end。

通过new_endvec.end()范围删除剩余元素

std::vector<int> vec = {1, 2, 3, 4, 5};
auto new_end = std::remove_if(vec.begin(), vec.end(), [](int n) {
    return n % 2 == 0; // 删除偶数
});
vec.erase(new_end, vec.end()); // 删除 2,4

4、push_back与emplace_back的区别

push_back与emplace_back的区别主要体现在对象构造方式和性能效率上

  • push_back:需要先构造一个完整的对象(临时对象或已有对象),再通过拷贝/移动构造函数将其添加到容器中
  • emplace_back:直接在容器的内存空间中调用对象的构造函数,无需临时对象,避免拷贝/移动

性能差异

  • 简单类型(如int)​:两者性能几乎无差异,因为int的构造/拷贝成本极低
  • 自定义复杂类型:emplace_back通过避免临时对象和拷贝操作,显著提升性能
    struct Complex { Complex(int, double); }; // 高成本构造函数
    vec.emplace_back(42, 3.14); // 直接构造,效率高
    vec.push_back(Complex(42, 3.14)); // 需先构造临时对象再拷贝

5、vector<bool> 使用的是bit,不能取地址 

三、高阶

1、如何快速释放vector的内存?

shrink_to_fit(); //请求容量等于大小(非强制)

std::vector<int>(vec).swap(vec);  // 强制释放多余内存

shrink_to_fit() 的实现与效果(内存地址改变,原容器的迭代器、指针、引用可能失效

目标:释放 vector 未使用的内存(即 capacity > size 的部分),使 capacity 尽可能接近 size

  • 创建临时容器:生成一个空的临时 vector,使用与原容器相同的分配器。
  • 预分配精确内存:临时容器调用 reserve(size),使其容量恰好等于原容器的当前元素数量(size)。
  • 复制元素:将原容器的所有元素复制到临时容器中。
  • 内存交换:通过 swap 交换两个容器的内部指针(指向数据内存、size 和 capacity 的指针)。
  • 销毁临时容器:临时容器析构时,释放原容器之前占用的多余内存。

std::vector<int>(vec).swap(vec) 的实现与效果

目标:通过构造临时对象并交换内存,强制将 capacity 缩减到 size

  • 构造临时对象std::vector<int>(vec) 调用复制构造函数,生成一个临时 vector。**新容器的 capacity 等于原容器的 size**​(因为复制构造函数仅复制元素,不保留多余容量)
  • 交换内存:通过 swap(vec) 交换临时容器与原容器的内部指针。
  • 销毁临时对象:临时对象析构时,释放原容器的旧内存(此时临时对象持有原容器的旧内存)。
  • 结果:原容器的 capacity 变为临时对象的 size,即精确匹配当前元素数量。

2、vectorlist的核心差异?

vector支持O(1)随机访问,插入/删除非尾部元素代价高;

list插入/删除任意位置高效,无法随机访问

3、移动语义在vector中的应用?

std::vector<std::string> v1 = {"a", "b"};
std::vector<std::string> v2 = std::move(v1);  // v1变为空,v2接管资源

4、自定义分配器如何与vector结合?

通过模板参数指定分配器类型

std::vector<int, MyAllocator<int>> v;  // 使用自定义分配器

5、vector里面的内存 总是连续的吗?

std::vector 的内存布局始终是连续的。std::deque 虽支持高效随机访问,但其内存布局为分段连续(通过多个独立块实现)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2309105.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

正式页面开发-登录注册页面

整体路由设计&#xff1a; 登录和注册的切换是切换组件或者是切换内容&#xff08;v-if和 v-else)&#xff0c;因为点击两个之间路径是没有变化的。也就是登录和注册共用同一个路由。登录是独立的一级路由。登录之后进到首页&#xff0c;有三个大模块&#xff1a;文章分类&…

Spring项目-抽奖系统(实操项目-用户管理接口)(END)

^__^ (oo)\______ (__)\ )\/\ ||----w | || || 一&#xff1a;前言&#xff1a; 活动创建及展示博客链接&#xff1a;Spring项目-抽奖系统(实操项目-用户管理接口)(THREE)-CSDN博客 上一次完成了活动的创建和活动的展示&#xff0c;接下来就是重头戏—…

Kafka面试题及原理

1. 消息可靠性&#xff08;不丢失&#xff09; 使用Kafka在消息的收发过程都会出现消息丢失&#xff0c;Kafka分别给出了解决方案 生产者发送消息到Brocker丢失消息在Brocker中存储丢失消费者从Brocker 幂等方案&#xff1a;【分布式锁、数据库锁&#xff08;悲观锁、乐观锁…

CSS—text文本、font字体、列表list、表格table、表单input、下拉菜单select

目录 1.文本 2.字体 3.列表list a.无序列表 b.有序列表 c.定义列表 4.表格table a.内容 b.合并单元格 3.表单input a.input标签 b.单选框 c.上传文件 4.下拉菜单 1.文本 属性描述color设置文本颜色。direction指定文本的方向 / 书写方向。letter-spacing设置字符…

水果识别系统 | BP神经网络水果识别系统,含GUI界面(Matlab)

使用说明 代码下载&#xff1a;BP神经网络水果识别系统&#xff0c;含GUI界面&#xff08;Matlab&#xff09; BP神经网络水果识别系统 一、引言 1.1、研究背景及意义 在当今科技迅速发展的背景下&#xff0c;人工智能技术尤其是在图像识别领域的应用日益广泛。水果识别作为…

40岁开始学Java:Java中单例模式(Singleton Pattern),适用场景有哪些?

在Java中&#xff0c;单例模式&#xff08;Singleton Pattern&#xff09;用于确保一个类只有一个实例&#xff0c;并提供全局访问点。以下是详细的实现方式、适用场景及注意事项&#xff1a; 一、单例模式的实现方式 1. 饿汉式&#xff08;Eager Initialization&#xff09; …

李宏毅机器学习课程学习笔记04 | 浅谈机器学习-宝可梦、数码宝贝分类器

文章目录 案例&#xff1a;宝可梦、数码宝贝分类器第一步&#xff1a;需要定义一个含有未知数的function第二步&#xff1a;loss of a function如何Sample Training Examples > 如何抽样可以得到一个较好的结果如何权衡模型的复杂程度 Tradeoff of Model Complexity todo 这…

Redis详解(实战 + 面试)

目录 Redis 是单线程的&#xff01;为什么 Redis-Key(操作redis的key命令) String 扩展字符串操作命令 数字增长命令 字符串范围range命令 设置过期时间命令 批量设置值 string设置对象,但最好使用hash来存储对象 组合命令getset,先get然后在set Hash hash命令: h…

ISP CIE-XYZ色彩空间

1. 颜色匹配实验 1931年&#xff0c;CIE综合了前人实验数据&#xff0c;统一采用700nm&#xff08;红&#xff09;、546.1nm&#xff08;绿&#xff09;、435.8nm&#xff08;蓝&#xff09;​作为标准三原色波长&#xff0c;绘制了色彩匹配函数&#xff0c;如下图。选定这些波…

【强化学习笔记1】从强化学习的基本概念到近端策略优化(PPO)

好久没有更新了。最近想学习一下强化学习&#xff0c;本系列是李宏毅老师强化学习的课程笔记。 1. Policy-based Model 1.1 Actor 在policy-based model中&#xff0c;主要的目的就是训练一个actor。 对于一个episode&#xff08;例如&#xff0c;玩一局游戏&#xff09;&…

STM32中的ADC

目录 一&#xff1a;什么是ADC 二&#xff1a;ADC的用途 三&#xff1a;STM32F103ZET6的ADC 3.1ADC对应的引脚 3.2ADC时钟 3.3ADC的工作模式 ​编辑3.4ADC校准 3.5ADC转换结构和实际电压的换算 四&#xff1a;ADC配置步骤 五&#xff1a;两个重要的函数 一&#xff1a…

开启AI短剧新纪元!SkyReels-V1/A1双剑合璧!昆仑万维开源首个面向AI短剧的视频生成模型

论文链接&#xff1a;https://arxiv.org/abs/2502.10841 项目链接&#xff1a;https://skyworkai.github.io/skyreels-a1.github.io/ Demo链接&#xff1a;https://www.skyreels.ai/ 开源地址&#xff1a;https://github.com/SkyworkAI/SkyReels-A1 https://github.com/Skywork…

【uniapp】在UniApp中实现持久化存储:安卓--生成写入数据为jsontxt

在移动应用开发中&#xff0c;数据存储是一个至关重要的环节。对于使用UniApp开发的Android应用来说&#xff0c;缓存&#xff08;Cache&#xff09;是一种常见的数据存储方式&#xff0c;它能够提高应用的性能和用户体验。然而&#xff0c;缓存数据在用户清除缓存或清除应用数…

使用IDEA如何隐藏文件或文件夹

选择file -> settings 选择Editor -> File Types ->Ignored Files and Folders (忽略文件和目录) 点击号就可以指定想要隐藏的文件或文件夹

git从零学起

从事了多年java开发&#xff0c;一直在用svn进行版本控制&#xff0c;如今更换了公司&#xff0c;使用的是git进行版本控制&#xff0c;所以打算记录一下git学习的点滴&#xff0c;和大家一起分享。 百度百科&#xff1a; Git&#xff08;读音为/gɪt/&#xff09;是一个开源…

汽车低频发射天线介绍

汽车低频PKE天线是基于RFID技术的深度研究及产品开发应用的一种天线&#xff0c;在汽车的智能系统中发挥着重要作用&#xff0c;以下是关于它的详细介绍&#xff1a; 移动管家PKE低频天线结构与原理 结构&#xff1a;产品一般由一个高Q值磁棒天线和一个高压电容组成&#xff…

【Java分布式】Nacos注册中心

Nacos注册中心 SpringCloudAlibaba 也推出了一个名为 Nacos 的注册中心&#xff0c;相比 Eureka 功能更加丰富&#xff0c;在国内受欢迎程度较高。 官网&#xff1a;https://nacos.io/zh-cn/ 集群 Nacos就将同一机房内的实例划分为一个集群&#xff0c;一个服务可以包含多个集…

5G学习笔记之BWP

我们只会经历一种人生&#xff0c;我们选择的人生。 参考&#xff1a;《5G NR标准》、《5G无线系统指南:如微见著&#xff0c;赋能数字化时代》 目录 1. 概述2. BWP频域位置3. 初始与专用BWP4. 默认BWP5. 切换BWP 1. 概述 在LTE的设计中&#xff0c;默认所有终端均能处理最大2…

(十一)基于vue3+mapbox-GL实现模拟高德实时导航轨迹播放

要在 Vue 3 项目中结合 Mapbox GL 实现类似高德地图的实时导航轨迹功能,您可以按照以下步骤进行: 安装依赖: 首先,安装 mapbox-gl 和 @turf/turf 这两个必要的库: npm install mapbox-gl @turf/turf引入 Mapbox GL: 在组件中引入 mapbox-gl 并初始化地图实例: <templ…

【Transformer模型学习】第三篇:位置编码

文章目录 0. 前言1. 为什么需要位置编码&#xff1f;2. 如何进行位置编码&#xff1f;3. 正弦和余弦位置编码4. 举个例子4.1 参数设置4.2 计算分母项4.3 计算位置编码4.4 位置编码矩阵 5. 相对位置信息6. 改进的位置编码方式——RoPE6.1 RoPE的核心思想6.2 RoPE的优势 7. 总结 …