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

vector 面试点总结

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

一、入门

1、什么是vector

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

2、怎么创建-初始化vector

std::vector<int> v;  // 创建空vectorstd::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 虽支持高效随机访问,但其内存布局为分段连续(通过多个独立块实现)

相关文章:

vector 面试点总结

ps&#xff1a;部分内容使用“AI”查询 一、入门 1、什么是vector 动态数组容器&#xff0c;支持自动扩容、随机访问和连续内存存储。 2、怎么创建-初始化vector std::vector<int> v; // 创建空vectorstd::vector<int> v {1, 2, 3}; // 直接初始化std::vec…...

Java 8 新特性

Java 8 引入了一系列重要的新特性&#xff0c;极大地增强了 Java 语言的功能&#xff0c;尤其是在 函数式编程、流处理、日期时间 API 和 默认方法 等方面。这些新特性不仅提升了代码的可读性和简洁性&#xff0c;还改善了并发处理的性能。以下是 Java 8 主要新特性的详细说明。…...

知识库技术选型:主流Embedding模型特性对比

知识库技术选型&#xff1a;主流Embedding模型特性对比 1. 知识库与大模型结合的背景 知识库是存储和管理结构化知识的系统&#xff0c;广泛应用于问答系统、推荐系统和搜索引擎等领域。随着大语言模型&#xff08;LLM&#xff09;的发展&#xff0c;知识库与大模型的结合成为…...

CAN总线通信协议学习2——数据链路层之帧格式

1 帧格式 帧格式可理解为定义了传输的数据&#xff08;叫报文&#xff09;应该“长什么样”来传输&#xff0c;也为后续设定一些规则如错误检查机制提供了思路。 首先&#xff0c;帧格式可分为以下5种类型&#xff1a; PS&#xff1a;CAN总线任意一个设备可当收也可当发&#…...

基于ArcGIS Pro、Python、USLE、INVEST模型等多技术融合的生态系统服务构建生态安全格局高阶应用

文字目录 前言第一章、生态安全评价理论及方法介绍一、生态安全评价简介二、生态服务能力简介三、生态安全格局构建研究方法简介 第二章、平台基础一、ArcGIS Pro介绍二、Python环境配置 第三章、数据获取与清洗一、数据获取&#xff1a;二、数据预处理&#xff08;ArcGIS Pro及…...

神经网络在电力电子与电机控制中的应用

神经网络&#xff08;Neural Networks&#xff09;简介 神经网络是一种受生物神经元启发的机器学习模型&#xff0c;能够通过大量数据学习输入与输出之间的非线性映射关系。其核心结构包括&#xff1a; 输入层&#xff1a;接收外部数据&#xff08;如传感器信号、控制指令&…...

llama-factory || AutoDL平台

报错如下&#xff1a; rootautodl-container-d83e478b47-3def8c49:~/LLaMA-Factory# llamafactory-cli webui * Running on local URL: http://0.0.0.0:7860Could not create share link. Missing file: /root/miniconda3/lib/python3.10/site-packages/gradio/frpc_linux_am…...

数学建模:MATLAB极限学习机解决回归问题

一、简述 极限学习机是一种用于训练单隐层前馈神经网络的算法&#xff0c;由输入层、隐藏层、输出层组成。 基本原理&#xff1a; 输入层接受传入的样本数据。 在训练过程中随机生成从输入层到隐藏层的所有连接权重以及每个隐藏层神经元的偏置值&#xff0c;这些参数在整个…...

力扣785. 判断二分图

力扣785. 判断二分图 题目 题目解析及思路 题目要求将所有节点分成两部分&#xff0c;每条边的两个端点都必须在不同集合中 二分图&#xff1a;BFS/DFS/并查集 因为图不一定联通&#xff0c;所以枚举所有点都做bfs(如果没联通的话) 代码 class Solution { public:bool is…...

【硬件工程师成长】之是否需要组合电容进行滤波的考虑

在电子电路设计中&#xff0c;判断是否需要使用组合电容进行滤波&#xff0c;需综合考虑以下因素&#xff1a; 1. 噪声频谱分析 高频与低频噪声共存&#xff1a;若电源或信号中同时存在低频&#xff08;如工频纹波&#xff09;和高频噪声&#xff08;如开关电源的开关噪声、数字…...

Pythonweb开发框架—Flask工程创建和@app.route使用详解

1.创建工程 如果pycharm是专业版&#xff0c;直接NewProject—>Flask 填写工程name和location后&#xff0c;点击右下角【create】&#xff0c;就会新建一个flask工程&#xff0c;工程里默认会建好一个templates文件夹、static文件夹、一个app.py文件 templates&#xff1…...

005 公网访问 docker rocketmq

文章目录 创建自定义网络创建NameServer容器创建Broker容器正式开始启动 Nameserver 容器启动 Broker 容器并关联 Nameserverdocker exec -it rmqbroker vi /etc/rocketmq/broker.conf检查 namesrv 解析检查 Broker 注册状态Nameserver 日志Broker 日志检查容器日志手动指定 Br…...

C++11中的右值引用和完美转发

C11中的右值引用和完美转发 右值引用 右值引用是 C11 引入的一种新的引用类型&#xff0c;用 && 表示。它主要用于区分左值和右值&#xff0c;并且可以实现移动语义&#xff0c;避免不必要的深拷贝&#xff0c;提高程序的性能。左值通常是可以取地址的表达式&#xf…...

txt 转 json 使用python语言

需求: 把如下的txt文档转成json输出 代码 import jsondef txt_to_json(input_file, output_file):data_list []with open(input_file, r, encodingutf-8) as f:for line in f:# 分割数据并去除换行符parts line.strip().split(,)print(f"{parts}")print(type(par…...

Android Logcat 高效调试指南

工具概览 Logcat 是 Android SDK 提供的命令行日志工具&#xff0c;支持灵活过滤、格式定制和实时监控&#xff0c;官方文档详见 Android Developer。 基础用法 命令格式 [adb] logcat [<option>] ... [<filter-spec>] ... 执行方式 直接调用&#xff08;通过ADB守…...

【Linux】从入门到精通:Make与Makefile完全指南

欢迎来到 CILMY23 的博客 &#x1f3c6;本篇主题为&#xff1a;从入门到精通&#xff1a;Make与Makefile完全指南 &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;C | C语言 | Linux | Python | 数据结构和算法 | 算法专题 &#x1…...

leetcode0014 最长公共前缀 -easy

1 题目&#xff1a;最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 “”。 示例 1&#xff1a; 输入&#xff1a;strs [“flower”,“flow”,“flight”] 输出&#xff1a;“fl” 示例 2&#xff1a; 输入&a…...

【星云 Orbit-F4 开发板】07. 用判断数据尾来接收据的串口通用程序框架

【星云 Orbit-F4 开发板】用判断数据尾来接收一串数据的串口通用程序框架 摘要 本文介绍了一种基于STM32F407微控制器的串口数据接收通用程序框架。该框架通过判断数据尾来实现一串数据的完整接收&#xff0c;适用于需要可靠数据传输的应用场景。本文从零开始&#xff0c;详细…...

LLVM - 编译器前端 - 将源文件转换为抽象语法树(一)

一:概述 编译器通常分为两部分——前端和后端。在本文中,我们将实现编程语言的前端部分——即主要处理源语言的部分。我们将学习现实世界编译器使用的技术,并将其应用到我们的编程语言中。 本文将从定义编程语言的语法开始,最终生成一个抽象语法树(AST),这是代码生成的基…...

02_NLP文本预处理之文本张量表示法

文本张量表示法 概念 将文本使用张量进行表示,一般将词汇表示为向量,称为词向量,再由各个词向量按顺序组成矩阵形成文本表示 例如: ["人生", "该", "如何", "起头"]># 每个词对应矩阵中的一个向量 [[1.32, 4,32, 0,32, 5.2],[3…...

别再只用默认样式了!手把手教你定制LVGL Bar进度条的3种高级视觉效果

突破视觉边界&#xff1a;LVGL进度条高级定制技法三则 在嵌入式UI开发领域&#xff0c;LVGL以其轻量级和高度可定制性赢得了众多开发者的青睐。但当我们超越基础功能实现&#xff0c;进入视觉表现力的深水区时&#xff0c;这个开源图形库的真正魅力才开始显现。进度条作为人机交…...

基于EM9283与FPGA的工业便携式WiFi数据终端设计实战

1. 项目概述&#xff1a;一个工业现场的便携式WiFi数据终端在工业现场&#xff0c;数据采集与无线传输的需求无处不在&#xff0c;但环境往往复杂多变&#xff1a;布线困难、设备需要移动、供电不便。传统的方案要么是拖着长长的线缆&#xff0c;要么是依赖工控机加外置模块&am…...

RTX166任务调度:K_IVL与K_TMO事件机制详解

1. RTX166任务调度中的K_IVL与K_TMO事件机制解析在RTX166实时操作系统中&#xff0c;os_wait函数提供的K_IVL和K_TMO事件是任务调度的核心机制。这两个看似相似的延时控制参数&#xff0c;在实际应用中却有着截然不同的行为模式。作为深耕嵌入式领域十余年的开发者&#xff0c;…...

Kettle的优势

Kettle说具有非常强大的数据处理功能&#xff0c;没有做不到只有你想不到或者你还没有学会使用&#xff0c;如果确实做不到的情况下你还可以开发插件来进行数据处理&#xff0c;其中Kettle也提供了广泛的数据处理和转换功能&#xff0c;包括数据抽取、清洗、转换、合并、过滤等…...

泳装电商运营——AI驱动增长新引擎

泳装电商运营——AI驱动增长新引擎泳装旺季营销攻略&#xff1a;如何用AI工具实现销量翻倍&#xff1f;泳装行业的季节性特征明显&#xff0c;旺季不旺是很多商家的痛点。如何在短短几个月的销售窗口期内最大化产出&#xff1f;北京先智先行科技有限公司的一站式AI营销解决方案…...

昇腾CANN amct:模型压缩工具的量化和部署实践

amct&#xff08;Ascend Model Compression Toolkit&#xff09;是 CANN 内置的模型压缩工具&#xff0c;不是 AtomGit 上的独立开源仓库——它在 CANN AOE 调优引擎里作为一个子模块运行。amct 做三件事&#xff1a;量化&#xff08;INT8/FP16&#xff09;、剪枝&#xff08;结…...

AI时代管理者必备的10项核心能力地图

1. 项目概述&#xff1a;这不是一份“领导力清单”&#xff0c;而是一张AI时代管理者的生存地图“10 Essential Skills for AI Leaders”——看到这个标题&#xff0c;很多人第一反应是点开、收藏、转发到“管理者必读”群&#xff0c;然后继续用Excel做季度复盘、用PPT讲战略愿…...

手把手教你用Mosquitto + PowerShell玩转MQTT消息订阅与发布(实战测试篇)

手把手教你用Mosquitto PowerShell玩转MQTT消息订阅与发布&#xff08;实战测试篇&#xff09; MQTT协议作为物联网领域的核心通信标准&#xff0c;其轻量级和发布/订阅模式为设备互联提供了高效解决方案。本文将带您通过Windows PowerShell与Mosquitto搭建完整的MQTT测试环境…...

麒麟系统(桌面版)安装 NVIDIA 显卡驱动

麒麟系统&#xff08;桌面版&#xff09;安装 NVIDIA 显卡驱动 一、确认系统和显卡信息 # 查看系统版本 cat /etc/kylin-release# 查看内核版本 uname -r# 查看显卡型号 lspci | grep -i nvidia二、更新系统并安装编译依赖 sudo apt update && sudo apt upgrade -y sud…...

B/S架构模式在校园管理系统中的应用研究

随着校园信息化建设的不断普及&#xff0c;各类校园管理系统层出不穷&#xff0c;系统架构模式直接决定系统的使用便捷性、运维难度与适配场景。传统C/S架构即客户端/服务器架构&#xff0c;需要用户下载安装专属客户端&#xff0c;存在部署繁琐、升级困难、跨终端适配差、运维…...