积加科技音视频一面
音视频/多媒体/流媒体开发面试系列,欢迎订阅收藏。
1. C++ STL中map
和unordered_map
区别?
考察点: 数据结构理解、STL容器特性、性能分析
答题思路: 从底层实现、时间复杂度、内存使用、使用场景等角度对比
参考回答:
- 底层实现:
map
基于红黑树(平衡二叉搜索树),unordered_map
基于哈希表 - 时间复杂度:
map
的查找/插入/删除为O(log n),unordered_map
平均O(1),最坏O(n) - 有序性:
map
保持key的有序性,支持范围查询;unordered_map
无序 - 内存开销:
map
需要额外存储树节点指针,unordered_map
需要哈希表空间 - 使用场景:需要有序遍历或范围查询用
map
,追求查找性能用unordered_map
2. 虚函数表存放位置
考察点: C++内存模型、虚函数机制、面向对象原理
答题思路: 从存储位置、生命周期、数量等角度回答
参考回答:
- 存放位置:虚函数表存放在程序的静态存储区(全局数据段)
- 表的数量:每个包含虚函数的类有一份虚函数表
- 对象中的指针:每个对象实例包含一个
vptr
指针指向类的虚函数表 - 继承关系:派生类有自己的虚函数表,包含重写的函数地址
- 生命周期:程序启动时创建,程序结束时销毁
3. shared_ptr是线程安全的吗?
考察点: 智能指针理解、多线程编程、C++11特性
答题思路: 区分引用计数和对象访问的安全性
参考回答:
部分线程安全:
- 引用计数操作是线程安全的:copy、赋值、析构等操作的计数更新是原子的
- 对象访问不是线程安全的:多线程同时读写同一个shared_ptr对象不安全
- 所管理对象的访问不是线程安全的:需要额外同步机制
安全使用方式:
- 多线程间传递shared_ptr副本是安全的
- 同时访问不同的shared_ptr实例是安全的
- 访问共享对象内容需要额外加锁保护
4. Memory order知道吗?
考察点: C++11内存模型、并发编程、底层系统理解
答题思路: 解释内存序概念和应用场景
参考回答:
Memory Order定义了多线程环境下内存操作的顺序约束:
主要类型:
memory_order_relaxed
:最宽松,只保证原子性memory_order_acquire
:获取语义,后续读写不能重排到前面memory_order_release
:释放语义,前面读写不能重排到后面memory_order_acq_rel
:同时具有获取和释放语义memory_order_seq_cst
:顺序一致性,最严格(默认)
应用场景: atomic操作、lock-free编程、性能优化
5. H264的流程 (着重说一下编码压缩的过程)
考察点: 视频编码原理、H.264标准理解、多媒体技术基础
答题思路: 按编码流程顺序讲解,重点说明压缩技术
参考回答:
- 帧分类:I帧(关键帧)、P帧(前向预测)、B帧(双向预测)
- 宏块划分:将图像分为16x16像素的宏块
- 帧内/帧间预测:利用空间和时间冗余进行预测
- 运动估计与补偿:寻找最佳匹配块,生成运动矢量
- 变换编码:对残差进行DCT变换
- 量化:根据QP值量化变换系数,控制压缩比
- 熵编码:使用CAVLC/CABAC进行无损压缩
- 环路滤波:去除块效应,提高图像质量
6.视频编码,15帧,qp范围10-20,其他条件无限制,1-2M码率文件, 设置目标码率100k,两个要求满足一个,出来的真实大小是什么。
考察点: 视频编码参数理解、QP与码率关系、实际编码经验
答题思路: 分析QP优先级、码率控制机制
参考回答:
当QP范围设置为10-20且目标码率为100k时:
- QP优先原则:多数编码器会优先保证QP范围,忽略码率限制
- QP 10-20属于高质量范围,会产生较大文件
- 最终大小仍会是1-2M,因为QP控制了量化程度
- 这是CQP(恒定QP)模式的特点,画质优先于码率控制
- 如需严格控制码率,应使用CBR或VBR模式
7. TCP拥塞控制有什么缺点,BBR知道吗?
考察点: 网络协议理解、拥塞控制算法、新技术认知
答题思路: 传统算法问题分析,BBR优势对比
参考回答:
TCP拥塞控制缺点:
- 慢启动过于保守,在高带宽网络下效率低
- 基于丢包检测,在无线网络中误判严重
- RTT敏感,长距离传输性能差
- 带宽利用率不足,特别是高BDP网络
BBR算法:
- 基于带宽和RTT建模,而非丢包
- 主动探测网络状态,实现最优吞吐量
- 四个状态:Startup、Drain、ProbeBW、ProbeRTT
- 显著提升性能,特别是长距离高带宽场景
8. select和epoll的区别?
考察点: I/O多路复用、Linux系统编程、高并发处理
答题思路: 从实现机制、性能、使用限制等对比
参考回答:
特性 | select | epoll |
---|---|---|
文件描述符限制 | 1024(FD_SETSIZE) | 无限制(受系统资源限制) |
时间复杂度 | O(n) | O(1) |
数据拷贝 | 每次调用都需要拷贝fd_set | 一次拷贝,内核维护 |
触发方式 | 水平触发 | 水平触发+边缘触发 |
跨平台性 | 好 | Linux专有 |
适用场景 | 连接数少或者windows | 高并发场景 |
9. Select是事件驱动机制吗?
考察点: 事件驱动概念理解、I/O模型分类
答题思路: 区分I/O多路复用和事件驱动的概念
参考回答:
- 事件驱动机制的定义
**事件驱动(Event-Driven)**是一种编程范式,具有以下特征:
- 异步响应:程序流程由事件的发生来驱动,而非顺序执行
- 事件循环:核心是一个事件循环(Event Loop),持续监听和分发事件
- 回调机制:当事件发生时,自动调用相应的回调函数处理
- 非阻塞:主线程不会被I/O操作阻塞,可以处理多个并发事件
- 松耦合:事件的产生者和消费者解耦,通过事件总线连接
- Select的工作机制分析
Select的特点:
- 同步I/O多路复用:一次监控多个文件描述符的状态变化
- 阻塞调用:调用select时会阻塞,直到有文件描述符就绪或超时
- 轮询检查:返回后需要遍历文件描述符集合,检查哪些就绪
- 状态查询:本质是查询I/O状态,而非真正的事件通知
- Select本身不是事件驱动机制:
- 同步阻塞:select调用会阻塞当前线程
- 主动轮询:需要主动检查哪些fd就绪,不是被动接收事件
- 无回调机制:没有自动的事件回调,需要手动处理
- 紧耦合:事件检测和事件处理在同一个流程中
- 虽然select本身不是事件驱动,但可以作为事件驱动架构的底层实现工具:
class EventLoop {
public:void addHandler(int fd, EventType type, Callback cb) {handlers_[fd][type] = cb;}void run() {while(running_) {// 使用select作为底层机制int ret = select(maxfd + 1, &readfds, &writefds, NULL, &timeout);// 将select结果转换为事件分发for(int i = 0; i < maxfd; ++i) {if(FD_ISSET(i, &readfds)) {// 触发事件回调 - 这里实现了事件驱动handlers_[i][READ_EVENT](i);}}}}
};