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

字节跳动 C++ QT PC客户端面试

字节跳动 C++ Qt PC客户端面试,总共三轮技术面(一面10道、二面20道、三面20道)

为了帮助更多的同学拿到满意的 offer,我把一二三面共50道面试题整理发布出来~供大家学习参考~

很多同学认为,面试问理论知识,就是八股文,实际工作中没有太大用处。但事实上,所谓的“八股文”,本质是经过提炼和标准化的专业术语和通用认知体系,它是我们高效沟通、协作和解决问题的基础。

换句话说,掌握并能准确使用这些“八股文”,不是为了应付面试,而是为了让我们在真实的工作场景中,更高效地表达、理解和落地复杂的技术问题。

话不多说,直接进入正题(更多八股文面试题,关注公钟呺[Linux教程]发送“面试”获取):

Part1一面(10道题)

面试题1:父子继承时构造函数和析构函数的顺序?析构时如何让父子类里的所有析构都调用一遍?


✅ 构造顺序:

  • 先父后子
  • :当创建一个派生类对象时,首先调用基类的构造函数,然后是派生类自己的构造函数。
  • 如果有多个基类(多继承),按照它们在继承列表中出现的顺序依次构造。

✅ 析构顺序:

  • 先子后父
  • :析构时与构造顺序相反。先执行派生类的析构函数,再执行基类的析构函数。
  • 如果基类析构函数不是 virtual,则通过基类指针删除派生类对象时不会触发派生类的析构函数,导致内存泄漏。

🧠 如何确保所有析构函数被调用?

  • 使用虚析构函数(在基类中定义为 virtual ~Base() {})。
  • 不要手动调用 delete this 或者重复释放同一对象。
  • 避免裸指针管理资源,优先使用智能指针(如 std::unique_ptr)。

面试题2:一个函数,如何让它在 main 函数之前执行?


✅ 方法一:全局变量初始化

int before_main = [](){// 这里写你想执行的代码std::cout << "Before main\n";return 0;
}();

✅ 方法二:静态局部变量 + 类型构造

struct BeforeMain {BeforeMain() {// 执行你想运行的代码std::cout << "Before main via static object\n";}
};
static BeforeMain bm; // 全局静态对象,在main前构造

⚠️ 注意事项:

  • 初始化顺序依赖于编译单元,不同文件中的全局变量初始化顺序不确定。
  • 可以使用 std::call_once 或设计模式控制顺序。

面试题3:可以在 C++ 的成员函数里调用 delete this 吗?


✅ 可以,但必须满足以下条件:

  • 对象是动态分配的(即通过 new 创建)。
  • 调用 delete this 后不能再访问该对象的任何成员(包括 this 指针)。
  • 成员函数不能是虚析构函数的一部分。
  • 必须确保没有其他线程或代码正在访问该对象。

📌 示例:

class MyClass {
public:void selfDestruct() {delete this;}
};
MyClass* obj = new MyClass();
obj->selfDestruct(); // 正确
// obj 已经无效,不能再访问

❌ 错误示例:

MyClass obj;
obj.selfDestruct(); // 错误!栈上对象不能 delete

面试题4: 如何保证只打开一个 exe,再次打开时激活旧窗口并最大化显示?


✅ Windows 实现方式(使用互斥量 + 窗口查找):

#include <windows.h>
#include <QApplication>
#include <QMainWindow>
int main(int argc, char *argv[]) {HANDLE hMutex = CreateMutexW(nullptr, FALSE, L"MyAppSingleInstanceMutex");if (GetLastError() == ERROR_ALREADY_EXISTS) {// 已存在实例,查找主窗口HWND hWnd = FindWindowW(L"Qt5QWindowIcon", nullptr); // 替换为你程序的类名if (hWnd) {ShowWindow(hWnd, SW_RESTORE);SetForegroundWindow(hWnd);ShowWindow(hWnd, SW_MAXIMIZE);}return 0;}QApplication app(argc, argv);QMainWindow window;window.setWindowTitle("Only One Instance");window.show();return app.exec();
}

🧠 原理:

  • 使用系统级互斥量防止重复启动。
  • 查找已有窗口并激活它。
  • 使用 Win32 API 控制窗口状态(最大化/恢复/置顶)。

面试题5:浏览器前进后退功能,使用哪种数据结构存放历史网页合适?


✅ 推荐数据结构:双栈结构(两个栈)

  • 一个栈保存“前进”路径。
  • 一个栈保存“后退”路径。

🔄 操作流程:

  • 访问新页面 → 当前页压入“后退栈”,清空“前进栈”。
  • 点击“后退” → 弹出“后退栈”顶部,压入“前进栈”。
  • 点击“前进” → 弹出“前进栈”顶部,压入“后退栈”。

🧩 替代方案:

  • 双向链表
  • :更灵活,支持任意方向导航,适合复杂浏览器行为。
  • vector + index
  • :简单实现,适用于轻量级应用。

面试题6:Qt 多线程技术有哪些?哪些只有 QThread 能做,QtConcurrent 办不到?


✅ Qt 支持的多线程技术:

技术

描述

QThread

最底层的线程类,需要手动管理线程生命周期

QtConcurrent::run()

简化版线程池任务提交,自动回收线程

QtConcurrent::map() / filter() / mappedReduced()

并行处理容器元素

QRunnable + QThreadPool

提交任务给线程池执行

QFuture + QFutureWatcher

异步任务监控

✅ QThread 特有的能力:

  • 自定义线程事件循环(可响应信号槽)
  • 更细粒度控制线程优先级、亲和性等
  • 可用于创建长期运行的后台服务线程

❌ QtConcurrent 的限制:

  • 无法直接操作线程事件循环
  • 不适合长时间运行的任务
  • 不支持自定义线程池配置

面试题7:C++11 有哪些智能指针?


✅ C++11 标准库提供的智能指针:

智能指针类型

行为描述

std::unique_ptr<T>

独占所有权,不可复制,可移动

std::shared_ptr<T>

共享所有权,引用计数自动管理

std::weak_ptr<T>

观察 shared_ptr,不增加引用计数,防止循环引用

在Qt框架中还扩展了QScopedPointer和QSharedPointer,它们功能类似标准库的unique_ptr和shared_ptr,但能和Qt的对象系统更好集成。这些智能指针的核心价值是自动管理内存,避免内存泄漏,让资源管理更安全高效。

面试题8:如何使用 C++ 发送 HTTP 请求,并下载文件?


✅ 方法一:使用 Qt 自带模块 QNetworkAccessManager

#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QFile>
void downloadFile(const QString& urlStr, const QString& savePath) {QNetworkAccessManager manager;QUrl url(urlStr);QNetworkRequest request(url);QNetworkReply* reply = manager.get(request);QObject::connect(reply, &QNetworkReply::finished, [=]() {if (reply->error() == QNetworkReply::NoError) {QFile file(savePath);if (file.open(QIODevice::WriteOnly)) {file.write(reply->readAll());file.close();qDebug() << "Download finished.";}} else {qDebug() << "Error:" << reply->errorString();}reply->deleteLater();});// 主线程阻塞等待(仅用于测试)QEventLoop loop;connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);loop.exec();
}

✅ 方法二:使用更高级的QNetworkReply,它能自动处理重定向和SSL加密。关键点在于正确管理内存,确保响应数据能完整写入文件,同时要注意错误处理和超时控制


面试题9:QWidget 和 QML 的技术本质和使用上的区别?

维度

QWidget

QML

技术本质

基于 C++ 的传统 UI 框架

基于声明式语言(类似 JavaScript)的 UI 框架

渲染机制

QPainter 直接绘制控件

场景图(Scene Graph)+ OpenGL 渲染

开发效率

C++ 编码为主,UI 设计较繁琐

QML 可视化布局,热重载方便

性能

CPU 渲染,适合桌面传统界面

GPU 加速渲染,适合动画和现代 UI

适用场景

传统桌面软件、工具类应用

移动端适配、动画丰富、UI 动态变化频繁的应用

跨平台

支持良好

支持良好,尤其适合移动端

📌 何时选择?

  • 需要高性能图形渲染、动画效果 → QML
  • 需要快速开发传统桌面应用 → QWidget

面试题10:Qt 的信号与槽,有哪几种连接方式?对应的应用场景是什么?(第五个参数)


✅ 连接方式(第五个参数):

参数

类型

说明

Qt::AutoConnection

默认值

自动选择 Direct 或 Queued,取决于线程

Qt::DirectConnection

直接调用

槽函数立即执行(同步)

Qt::QueuedConnection

队列调用

槽函数异步执行,跨线程安全

Qt::BlockingQueuedConnection

阻塞队列

槽函数异步执行,发送方线程阻塞直到完成(跨线程)

Qt::UniqueConnection

唯一连接

保证信号和槽之间只有一个连接(与其他组合使用)

✅ 应用场景举例:

连接方式

使用场景

Direct

同一线程内快速响应(如按钮点击)

Queued

跨线程通信(如主线程更新 UI)

BlockingQueued

需要返回结果的跨线程调用(谨慎使用)

Auto

通用默认选项,自动判断

🧠 示例:

connect(sender, &Sender::signalName, receiver, &Receiver::slotName, Qt::QueuedConnection);


Part2二面(20道题)

面试题11:GPU渲染和CPU渲染之间的区别是什么?

特性

CPU 渲染

GPU 渲染

运算核心

单核/多核通用处理器

大量并行计算单元

擅长任务

复杂逻辑控制、小数据处理

大规模并行计算(如图形像素处理)

内存访问

使用系统内存

使用显存(VRAM)

延迟

较高延迟

极低延迟,适合实时渲染

能耗

高功耗(复杂运算)

更高效能比

典型用途

文本编辑器、非图形应用

游戏引擎、视频播放、动画 UI

🧠 Qt 中:

  • QWidget 默认使用 QPainter + CPU 渲染。
  • QML 默认使用 Scene Graph + OpenGL/GLES + GPU 渲染。

面试题12:集成显卡用户进行渲染时,在编码阶段是走硬编还是软编?


✅ 硬编 vs 软编:

  • 硬编(Hardware Encoding)
  • :利用显卡硬件编码器(如 Intel Quick Sync、NVIDIA NVENC)加速视频压缩。
  • 软编(Software Encoding)
  • :完全由 CPU 计算完成,灵活性高但效率低。

✅ 编码阶段是否走硬编取决于:

  • 是否调用了支持硬编的库(如 FFmpeg、Media SDK)。
  • 当前平台是否支持该硬编接口(如 Windows 上 DirectX Video Acceleration)。
  • 显卡驱动是否正常安装。

集成显卡在编码阶段可以走硬编,但需要开发者主动选择合适的 API 和库。

面试题13:硬编/软编 和 GPU/CPU 渲染是一回事吗?


❌ 不是一回事,它们属于不同层级的概念:

维度

硬编/软编

GPU/CPU 渲染

层级

视频编码层

图形绘制层

功能

将视频帧压缩为 H.264/H.265 格式

在屏幕上绘制像素

硬件依赖

显卡编码器支持

显卡渲染管线支持

应用场景

视频录制、直播推流

UI 绘制、游戏画面显示

🧠 举例说明:

  • 一个程序可能使用 GPU 渲染 UI,但视频编码时仍使用软编(FFmpeg x264)。
  • 另一个程序可能使用 GPU 渲染 UI,同时使用硬编(NVENC)进行录屏编码。

关联性

    • GPU渲染 + 硬编:最优路径(显存→编码器,零拷贝)
    • GPU渲染 + 软编:需回传内存→CPU,性能损耗
    • CPU渲染 + 硬编:需上传内存→显存,仍有损耗
    • CPU渲染 + 软编:完全CPU路径,性能最低

面试题14:QCoreApplication::setAttribute作用


✅ 作用:

强制 Qt 应用程序使用 OpenGL ES(嵌入式系统使用的轻量级 OpenGL)而不是桌面版 OpenGL。

✅ 适用场景:

  • 移动端开发(Android/iOS)
  • 集成显卡或不支持完整 OpenGL 的设备
  • 需要跨平台兼容性(尤其是移动端)

📌 示例:

QApplication::setAttribute(Qt::AA_UseOpenGLES);
QApplication app(argc, argv);

⚠️ 注意:不是所有平台都支持 OpenGL ES(如某些 Windows 平台需安装 ANGLE)。

面试题15:QWidget 和 QML 在渲染层面的区别?

渲染机制

QWidget

QML

底层技术

QPainter + 软件光栅化

Scene Graph + GPU加速

更新流程

脏矩形标记 → 逐层重绘

场景图差异 → 批量提交GPU

透明度处理

逐层混合(性能差)

Shader一次合成(性能优)

动画性能

依赖定时器+重绘(CPU 渲染,性能有限)

属性绑定+GPU插值(GPU 加速,适合动画和复杂 UI)

抗锯齿

慢(CPU计算)

快(MSAA/FXAA)

典型帧率

30-60 FPS(复杂UI卡顿)

60+ FPS(流畅)

  • QWidget 更适合传统桌面工具类软件。
  • QML 更适合现代 UI、动画丰富、响应式设计的应用。

面试题16:Win11 对Qt有哪些新特性支持?


而且从界面表现来看,Qt 程序在 Win11 上也能很好地适配,比如支持圆角窗口、深色模式、DPI 缩放优化等现代 UI 特性。只要注意一些系统级别的适配(比如高分辨率支持、任务栏集成),基本上写一次代码就可以直接运行。”

如果项目有特殊需求,比如想利用 Win11 的一些新特性(如 Direct3D 渲染、触控支持、通知机制等),也可以通过调用 Windows SDK 接口来扩展功能,Qt 提供了良好的底层支持能力。

面试题17:Windows 下窗口刷新机制是立即刷新还是异步刷新?


✅ 异步刷新机制:

  • Windows 使用消息队列机制,UI 刷新请求被放入 WM_PAINT 消息中排队处理。
  • 控件不会立即重绘,而是等待操作系统调度 WM_PAINT 消息。

✅ 刷新流程:

  1. 调用 update() → 触发区域无效化。
  2. 系统将其合并到更新区域。
  3. 发送 WM_PAINT 消息给窗口过程。
  4. 调用 paintEvent() 完成实际绘制。

🧠 如何强制刷新?

widget->update(); // 推荐
widget->repaint(); // 强制同步刷新(慎用)

面试题18:父子窗口间的刷新管理?兄弟窗口间的刷新管理?如何让子窗口刷新,父窗口不刷新?


✅ 刷新机制:

  • 子窗口刷新不会影响父窗口。
  • 父窗口刷新会触发子窗口刷新(除非子窗口设置了 Qt::WA_OpaquePaintEvent 等优化标志)。

✅ 如何只刷新子窗口?

  • 调用 childWidget->update()。
  • 设置 Qt::WA_StaticContents 或 Qt::WA_NoSystemBackground 避免父窗口连带刷新。

✅ 如何避免父窗口刷新?

  • 使用 QWidget::setUpdatesEnabled(false) 临时禁用刷新。
  • 使用局部刷新(仅刷新特定区域)。

面试题19:兄弟窗口刷新重叠部分的流程和顺序?


✅ 流程:

  1. 检测两个窗口是否有重叠区域。
  2. 每个窗口独立收到 WM_PAINT 消息。
  3. Windows 会根据 Z-order(Z轴顺序)依次绘制窗口内容。

✅ 刷新顺序:

  • Z-order 最高的窗口最后绘制,覆盖前面的窗口。
  • 重叠区域由后绘制的窗口决定最终显示内容。

🧠 如何精确控制刷新顺序?

  • 使用 raise() 提升窗口层级。
  • 使用 QWidget::update(const QRect&) 刷新指定区域。

面试题20:Windows 下 UAC 安全机制


✅ UAC(User Account Control)的作用:

  • 防止恶意程序以管理员权限运行。
  • 用户操作时提示确认,增强系统安全性。

✅ 工作原理:

  • 所有进程默认以标准用户权限运行。
  • 需要管理员权限的操作会弹出 UAC 对话框。
  • 成功授权后,系统创建新的“提升令牌”启动进程。

✅ 开发者注意事项:

  • 需要管理员权限的程序应添加 requestedExecutionLevel 到 .exe.manifest 文件。
  • 避免频繁请求 UAC 权限,影响用户体验。

面试题21:Windows 内存管理与共享内存实现


✅ 内存管理机制:

  • 虚拟内存:每个进程拥有独立地址空间。
  • 分页机制:将物理内存划分为页,按需加载。
  • 内存保护:防止非法访问其他进程内存。

✅ 共享内存实现方式:

  1. 文件映射(File Mapping)
  2. 使用 CreateFileMapping 和 MapViewOfFile。
  3. 多进程可读写同一块内存区域。
  4. 共享内存段(Shared Memory Segment)
  5. 通过注册表或命名对象共享句柄。

✅ Qt 实现共享内存:

#include <QSharedMemory>
QSharedMemory shared("my_shared_memory");
if (!shared.create(1024)) {qDebug() << "Failed to create shared memory";
}

面试题22:如何分析 dump 文件?


✅ 方法一:使用 Visual Studio

  • 打开 .dmp 文件 → 自动识别崩溃上下文。
  • 查看调用栈、寄存器状态、异常信息。

✅ 方法二:使用 WinDbg(推荐)

  • 安装 Windows SDK。
  • 使用命令:
.symfix
.reload
!analyze -v
  • 输出详细的崩溃原因、堆栈、函数名。

✅ 方法三:使用第三方工具

  • ProcDump
  • :生成 dump 文件。
  • CDB
  •  / ADPlus:脚本化调试工具。

面试题:23:如何排查代码中的内存泄漏问题(线上)?


✅ 本地调试方法:

  • 使用 Valgrind(Linux)、Visual Leak Detector(Windows)。
  • 使用 AddressSanitizer(ASan)静态检测内存问题。

✅ 线上排查方法:

  • 日志记录
  • :记录内存分配释放情况。
  • 工具辅助
    • CRT Debug Heap(Windows)
    • :_CrtSetDbgFlag 启用内存泄漏检测。
    • Valgrind + Dr.Memory
    • :远程执行测试。
  • Core Dump + 分析工具
  • :分析崩溃时的内存状态。

✅ Qt 方案:

  • 使用 qDebug() 打印对象生命周期。
  • 使用 QObject 的父子关系自动管理内存。

面试题24:QString 和 string 的区别及实现方式

维度

QString

std::string

字符编码

UTF-16(基于 QChar)

ASCII/UTF-8

所属库

Qt

C++ STL

内存管理

Qt 自定义分配器

STL 默认分配器

可变性

可变字符串

可变(C++11 后)

线程安全

Qt 管理

无内建线程安全

性能

Qt 优化过

STL 通用优化

面试题25:Qt 下如何使用多线程?


✅ 方法总结:

方法

描述

QThread

创建线程对象,继承并重写 run()

QRunnable + QThreadPool

提交任务到线程池,复用线程

QtConcurrent::run()

简单任务异步执行

QFuture + QFutureWatcher

异步监控任务状态

moveToThread()

将 QObject 移动到另一个线程,配合信号槽通信

✅ 示例:

class Worker : public QObject {Q_OBJECT
public slots:void doWork() {// 执行耗时操作}
};
Worker* worker = new Worker();
QThread* thread = new QThread(this);
worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &Worker::doWork);
connect(worker, &Worker::finished, thread, &QThread::quit);
connect(worker, &Worker::finished, worker, &QObject::deleteLater);
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
thread->start();

面试题26:show()和 exec()的区别

方法

所属类

行为描述

show()

QWidget

显示窗口,不阻塞主线程

exec()

QDialog/QApplication

显示模态对话框或进入主事件循环,阻塞当前线程

✅ 示例:

QDialog dialog;
dialog.exec(); // 阻塞直到对话框关闭
QMainWindow window;
window.show(); // 不阻塞

面试题27:QObjectparent 的用处


✅ 主要作用:

  • 自动内存管理
  • :当 parent 被删除时,所有 child 对象也会被递归删除。
  • 组织结构
  • :便于管理和查找对象树。
  • 父子关系传递属性
  • :如 enabled、visible 状态。

✅ 示例:

QObject* parent = new QObject;
QObject* child = new QObject(parent); // child 自动加入 parent 的 children 列表
delete parent; // child 会被自动 delete

面试题28:class 前向声明和 include 的区别

特性

前向声明

include

作用

告诉编译器某个类存在

包含类定义(成员变量、函数)

优点

减少编译依赖,加快编译速度

可以访问类成员

缺点

不能访问类成员

增加编译时间,可能导致循环依赖

✅ 使用建议:

  • 在头文件中尽可能使用前向声明。
  • 在源文件中包含完整头文件。

面试题29:多继承的问题


✅ 多继承的优点:

  • 代码复用性强。
  • 支持多种接口组合。

✅ 多继承的缺点:

  • 菱形继承问题
  • :多个基类继承同一个祖先,导致歧义。
  • 命名冲突
  • :同名函数/变量难以分辨。
  • 维护成本高
  • :继承层次复杂,不易理解。

✅ 解决方案:

  • 使用 virtual 关键字解决菱形继承。
  • 使用接口(纯虚类)替代具体类继承。
  • 优先使用组合代替继承。

面试题30:int,long long占多少字节


1. int

  • 在32位和64位系统中,通常占4字节(32位),表示范围约为±21亿。
  • 在嵌入式系统或特殊架构中可能为2字节(16位)。

2. long long:固定占8字节(64位),这是C++11标准明确规定的,范围极大(约±9.2×10¹⁸)。

在Qt开发中,qint64(Qt对long long的封装)同样保证8字节。


Part3三面(20道题)

面试题31: QGraphicsScene/ QGraphicsItem的填充模式,任意一个多边形的填充模式有哪些?


✅ 填充模式(Brush Style):

Qt 提供了多种 Qt::BrushStyle 枚举值用于控制图形项的填充方式:

枚举

描述

Qt::NoBrush

无填充

Qt::SolidPattern

实心填充

Qt::Dense1Pattern ~ Qt::Dense7Pattern

不同密度的点阵图案

Qt::HorPattern

横向条纹

Qt::VerPattern

纵向条纹

Qt::CrossPattern

十字交叉线

Qt::BDiagPattern

向右斜线

Qt::FDiagPattern

向左斜线

Qt::DiagCrossPattern

斜线十字交叉

✅ 多边形填充模式设置示例:

QPolygonF polygon;
polygon << QPointF(0, 0) << QPointF(100, 0) << QPointF(50, 100);
QGraphicsPolygonItem* item = new QGraphicsPolygonItem(polygon);
item->setBrush(Qt::red); // 默认是 SolidPattern

🧠 自定义纹理填充:

可以使用 QBrush(QPixmap) 或 QBrush(QImage) 设置图像作为填充图案。

面试题32:QGraphicsScene的内存开销与刷新性能


✅ 内存开销因素:

  • 场景中图形项的数量。
  • 图形项类型(如 QGraphicsPixmapItem 占用大)。
  • 是否启用了缓存(setCacheMode())。
  • 是否启用了碰撞检测或物理模拟。

✅ 刷新性能优化:

  • 使用 setViewportUpdateMode() 控制更新策略(如 BoundingRectViewportUpdate)。
  • 使用 setOptimizationFlag() 启用优化(如 DontSavePainterState)。
  • 避免频繁添加/删除大量图形项,应复用对象。
  • 对静态内容启用缓存(ItemCoordinateCache)。

QGraphicsScene 在处理大量动态图形时性能下降明显,适合中等复杂度的 UI 和图形编辑器。

面试题33:设计模式中的备忘录模式,如何实现撤销和恢复?


✅ 备忘录模式结构:

  • Originator(发起人)
  • :创建状态快照并恢复。
  • Memento(备忘录)
  • :保存状态数据。
  • Caretaker(管理者)
  • :负责存储备忘录,不查看其内容。

✅ 示例代码(简化):

class Memento {
public:explicit Memento(const QString& state) : m_state(state) {}QString getState() const { return m_state; }
private:QString m_state;
};
class Originator {
public:void setState(const QString& state) { m_state = state; }Memento saveToMemento() { return Memento(m_state); }void restoreFromMemento(const Memento& m) { m_state = m.getState(); }
};
class Caretaker {
public:void add(const Memento& m) { m_history.push_back(m); }Memento get(int index) { return m_history[index]; }
private:std::vector<Memento> m_history;
};

面试题:34:备忘录结构体如何保证扩展性?新增内容怎么办?


✅ 扩展性设计建议:

  • 使用 struct 或类封装状态信息。
  • 使用 JSON、Protobuf 等格式序列化状态,便于未来版本兼容。
  • 使用接口抽象状态管理,避免直接暴露内部结构。

✅ 新增字段不影响旧系统:

  • 使用版本号字段。
  • 使用可选字段(如 Protobuf 的 optional)。
  • 序列化时忽略未知字段。

面试题35:撤销20次后想一步跳到第20步怎么做?


✅ 解决方案:

  • 将所有历史步骤保存为列表(如 std::vector<Snapshot>)。
  • 直接访问索引 20 的状态进行恢复。

✅ 示例:

std::vector<State> history;
// ...
originator.restore(history[20]); // 一步到位

🧠 优势:

  • 时间复杂度 O(1),不需要迭代。
  • 支持“跳转”、“重做”等功能。

面试题36:云计算建立的连接是长连接吗?在哪一层建立?


✅ 长连接判断标准:

  • 如果连接持续时间长、数据交互频繁 → 长连接。
  • 如 WebSocket、gRPC、MQTT → 都是长连接。

✅ 连接建立层级:

  • 传输层(TCP/UDP)
  • :建立基本通信通道。
  • 应用层(HTTP/HTTPS/WebSocket)
  • :在 TCP 上建立业务连接。

✅ 举例:

  • HTTP 是短连接,默认每次请求新建连接。
  • WebSockets 是长连接,在 TCP 上建立持久通信。

面试题37:服务器轮询策略怎么做的?


✅ 轮询策略分类:

类型

描述

Round Robin

依次轮流分配

Least Connections

分配给当前连接最少的服务器

IP Hash

根据客户端 IP 哈希分配

Weighted RR

加权轮询,按服务器性能分配

✅ 实现方式:

  • Nginx、HAProxy 等反向代理配置。
  • 自定义负载均衡模块(如 C++ 编写)。

面试题38:Protocol Buffers 的问题(常见)


✅ 常见问题及解决方案:

问题

解决方法

字段变更导致兼容性问题

使用 optional 字段,避免 required;保留编号

数据解析失败

检查 proto 版本是否一致

序列化效率低

使用 flatbuffers、capnproto 等替代方案

无法跨语言兼容

使用官方支持的语言插件生成代码

面试题39:对性能和质量如何考量?


✅ 性能指标:

  • CPU 使用率
  • 内存占用
  • 启动时间
  • 响应延迟
  • 渲染帧率(UI 应用)

✅ 质量保障:

  • 单元测试 + 集成测试覆盖率
  • 静态分析(Clang-Tidy、Cppcheck)
  • 动态检测(Valgrind、AddressSanitizer)
  • 日志监控 + 异常捕获 + Core Dump

面试题40:CPU 并行化的方法(说一个熟悉的)


✅ OpenMP 示例(C++):

#include <omp.h>
#pragma omp parallel for
for (int i = 0; i < 1000; ++i) {// 并行执行的任务
}

✅ 优点:

  • 简单易用,适合循环并行。
  • 支持多核 CPU。

面试题41:静态扫描 vs 动态检测:C++ 内存动态检测怎么做?


✅ 动态检测工具:

  • Valgrind(Linux)
  • AddressSanitizer(ASan)
  • Dr.Memory(Windows)
  • Visual Studio CRT Debug Heap

✅ 使用 ASan 示例:

g++ -fsanitize=address -g your_code.cpp
./a.out

面试题42:如何判断一块内存是否正在使用还是泄漏?


✅ 方法:

  • 使用内存检测工具(如 Valgrind、ASan)。
  • 使用智能指针自动释放资源。
  • 使用引用计数(如 shared_ptr)。
  • 使用调试标记记录内存分配/释放。
struct MemHeader {void* stack[10]; // 分配调用栈size_t size;     // 分配大小bool isActive;   // 使用标志
};// 自定义分配器
void* operator new(size_t size) {void* p = malloc(size + sizeof(MemHeader));MemHeader* h = static_cast<MemHeader*>(p);captureStackTrace(h->stack); // 记录调用栈h->size = size;h->isActive = true;return static_cast<char*>(p) + sizeof(MemHeader);
}

面试题43:堆内存分配不足怎么办?


✅ 处理方式:

  • 抛出 std::bad_alloc 异常。
  • 返回 nullptr(new(std::nothrow))。
  • 触发内存回收机制(GC)。
  • 增加虚拟内存(Swap)。
void* allocateLargeBlock(size_t size) {void* p = malloc(size);if (!p) {// 尝试释放预留缓存releaseEmergencyPool();p = malloc(size);if (!p) throw std::bad_alloc();}return p;
}// 预分配应急内存
static char emergencyBuffer[10 * 1024 * 1024]; // 10MB
void releaseEmergencyPool() {free(emergencyBuffer); // 释放应急池
}

系统级策略

  • Linux Overcommit:/proc/sys/vm/overcommit_memory
  • Windows:MEM_RESERVE + MEM_COMMIT

面试题44:静态扫描检测的具体方法


✅ 工具与流程:

  • Clang-Tidy
  • :检查代码风格和潜在 bug。
  • Cppcheck
  • :静态分析逻辑错误。
  • Coverity、Klocwork
  • :商业级静态分析工具。
  • CI 中集成
  • :提交代码前自动扫描。

面试题45:工程效率方面 ,build system用的哪一块,qmake还是cmake.你们三方库管理,仓库管理,开发的模式,是怎么做的


✅ Build System:

  • qmake
  • :适用于小型项目,简单快捷。
  • CMake
  • :现代项目首选,跨平台,灵活强大。

✅ 三方库管理:

  • vcpkg
  • (微软推荐)
  • Conan
  • FetchContent(CMake 内置)
  • Git Submodule / External Project

✅ 开发模式:

  • Git Flow
  • Feature Branch
  • Code Review(GitHub/GitLab PR)

面试题46:算法工程师打包好动态库,是直接拖入你们的仓库里吗,你们是如何管理的


  • 使用 Conan / vcpkg 管理依赖。
  • 自建私有仓库(Artifactory、Nexus)。
  • CI 流程中自动构建、上传、签名。
  • 版本化命名(如 libalgo_v1.2.dll)。

面试题47:有没有自动化的过程,工程效率相关的


  • CI/CD 流程(Jenkins、GitLab CI、GitHub Actions)
  • 代码格式化(clang-format、prettier)
  • 静态分析(Cppcheck、SonarQube)
  • 文档自动生成(Doxygen)
  • 单元测试自动运行

面试题48:有CI/CD的部署吗,持续集成Continuous Integration(CI)和持续交付Continuous Delivery(CD)


CI(持续集成)

    • 代码提交触发构建
    • 自动运行单元测试
    • 生成构建产物(exe/dll)

CD(持续交付)

    • 自动部署到测试环境
    • 审核后发布到生产环境

✅ 工具:

  • Jenkins
  • GitHub Actions
  • GitLab CI
  • Azure DevOps

面试题49:sever的上线部署的流程是怎么样的


型上线流程:

  • 开发完成 → 提交代码 → Pull Request
  • CI 构建 → 单元测试通过 → 生成 release 包
  • 测试环境部署 → UAT 测试
  • 灰度发布 → 少量用户验证
  • 全量上线 → 正式环境部署
  • 日志监控 + 崩溃上报 + APM 监控

面试题50:一棵二叉树,节点都为正数,找出路径和等于 SUM 的所有路径


✅ 解法思路:

使用 DFS(深度优先搜索),递归遍历每个节点,并记录当前路径总和。

✅ 示例代码(C++):

struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
class Solution {
public:std::vector<std::vector<int>> pathSum(TreeNode* root, int sum) {std::vector<std::vector<int>> result;std::vector<int> path;dfs(root, sum, path, result);return result;}
private:void dfs(TreeNode* node, int remaining, std::vector<int>& path, std::vector<std::vector<int>>& result) {if (!node) return;path.push_back(node->val);if (!node->left && !node->right && remaining == node->val) {result.push_back(path);}dfs(node->left, remaining - node->val, path, result);dfs(node->right, remaining - node->val, path, result);path.pop_back();}
}

点击下方关注【Linux教程】,获取编程学习路线、项目教程、简历模板、大厂面试题、大厂面经、编程交流圈子等等。

http://www.xdnf.cn/news/1075537.html

相关文章:

  • Bessel位势方程求解步骤
  • OpenCV计算机视觉实战(14)——直方图均衡化
  • AutoCAD Electrical 2009无法激活
  • 通过python+openCV实现对图片中箭头方向的判断
  • 【Java面试】10GB,1GB内存,如何排序?
  • SQL参数化查询:防注入与计划缓存的双重优势
  • 「Java案例」计算矩形面积
  • 嵌入式SoC多线程架构迁移多进程架构开发技巧
  • 《用奥卡姆剃刀原理,为前端开发“减负增效”》
  • Ubuntu22.04 you are in emergency mode,键盘失效无法进入root命令行
  • 【Python使用】嘿马云课堂web完整实战项目第2篇:CMS页面管理需求,后端工程搭建【附代码文档】
  • Git 简介安装教程
  • vscode 改注释的颜色,默认是灰色的,想改成红色
  • 大数据(1)-hdfshbase
  • 【零基础学AI】第13讲:随机森林实战 - 用户行为预测
  • Spring Security 鉴权与授权详解(前后端分离项目)
  • 电脑开机加速工具,优化启动项管理
  • 服务器上设置了代理之后,服务器可以访问外网,但是不能访问服务器本地。如何解决
  • 重构老项目不再“踩雷”:飞算JavaAI的本地化智能合并实战
  • HarmonyOS NEXT应用元服务常见列表操作多类型列表项场景
  • 设计模式之外观模式
  • .net8导出影像图片按现场及天拆分
  • 调试W5500(作为服务器)
  • macos 使用 vllm 启动模型
  • 【微服务】.Net中使用Consul实现服务高可用
  • 51c大模型~合集144
  • 2025年光学工程、精密仪器与光电子技术国际会议(OEPIOT 2025)
  • 物联网基础
  • Git 常用命令、常用错误的总结
  • 2 大语言模型基础-2.2 生成式预训练语言模型GPT-2.2.2 有监督下游任务微调-Instruct-GPT强化学习奖励模型的结构改造与维度转换解析