美团 软件开发-C++ 一面

1. 自我介绍

2. 这里的数据量大小是多少,字幕使用mysql存储是不是不大合适,做分表操作必要性大吗?

答案:如果字幕数据量只是中等规模,而且查询模式比较明确,比如按视频 ID、语言、时间轴版本去查,MySQL 其实也不是完全不能用,关键在于表结构设计、索引设计和冷热数据策略是否合理。但如果字幕文本本身很长,写入频繁、版本多,而且还有检索、回溯、批量更新这类需求,那单纯放在 MySQL 里就不一定划算了。因为它更适合做结构化数据管理,不太适合承载高频大文本读写。更常见的做法会是 MySQL 存元数据和索引信息,大文本内容放对象存储或者专门的文档型存储里。至于分表有没有必要,要看几个点:单表行数、索引膨胀情况、写入压力、查询是否已经明显变慢,以及是否出现了归档压力。如果现在数据规模还远没到瓶颈,分表未必是第一选择,因为它会带来路由、扩容、聚合查询、运维复杂度这些额外成本。所以我会倾向于先做数据量级评估、热点分析和 SQL 画像,再决定是先优化索引和存储结构,还是真的上分表。

3. 我看你之前实习过测试, 怎么又接着做开发了

4. 你为什么封装这个网络接口,有了解原来接口怎么实现通信的吗?

答案:我封装网络接口,主要不是为了“再套一层”,而是为了把请求发送、连接管理、超时控制、错误处理这些共性逻辑收敛起来,避免业务层到处散落重复代码。如果业务代码直接去操作底层网络细节,短期开发可能快一点,但后面一旦协议变更、超时策略调整、重试逻辑变化,改动面会很大,也不利于排查问题。做接口封装之后,业务层更关注参数和结果,底层细节集中处理,可维护性会好很多。至于原来接口怎么通信,我是有了解过的。底层本质上还是基于 socket 做事件驱动通信,在 Linux 下通常会结合 epoll 去监听可读可写事件,然后在事件到来时触发回调,完成连接建立、数据收发和状态切换。像这种封装,真正要解决的不是“能不能发出去”,而是异常怎么处理、连接怎么复用、半包粘包怎么兼容、超时和重试怎么设计,以及接口如何对上层保持稳定。

5. libevent底层原理,回答了epoll的相关内容

答案:libevent 本质上是一个事件驱动库,它做的事情是把 I/O 复用、事件注册、事件分发和回调执行这一整套流程封装起来。在 Linux 下,它通常会优先使用 epoll 作为底层多路复用机制。epoll 负责监听大量文件描述符的事件状态,比如可读、可写、异常等;libevent 再在这个基础上维护事件集合、回调函数和事件循环。它的核心流程可以理解成几步:先把感兴趣的 fd 和事件注册到底层复用器里,然后进入 event loop,不断等待内核返回就绪事件;一旦有事件触发,libevent 会找到对应的回调并执行。相比传统的阻塞 I/O 或者简单轮询,这种方式的好处是可以在单线程下高效管理大量连接,避免线程数太多带来的切换开销。如果从工程角度看,libevent 解决的不只是监听事件,还包括定时器、信号、事件优先级这些能力,所以它比直接手写 epoll 用起来更完整。

代码:

#include <event2/event.h>
#include <iostream>
using namespace std;

void cb(evutil_socket_t fd, short events, void* arg) {
    cout << "fd " << fd << " readable" << endl;
}

int main() {
    event_base* base = event_base_new();
    event* ev = event_new(base, 0, EV_READ | EV_PERSIST, cb, nullptr);
    event_add(ev, nullptr);
    event_base_dispatch(base);
    event_free(ev);
    event_base_free(base);
    return 0;
}

6. 你能实习多久

7. C++98和C++11相比,多引入了哪些?

答案:C++11 相比 C++98 是一次很大的升级,不只是语法糖,而是让现代 C++ 的写法基本成型了。比较核心的变化包括右值引用和移动语义,这让对象转移资源变得更高效;autodecltype 提高了类型推导能力;nullptr 解决了空指针语义不清的问题;范围 forlambda 让代码表达更自然;智能指针进入标准库之后,资源管理也更规范。另外还有线程库、原子操作、unordered_mapstatic_assert、初始化列表、override/final 这些,基本把语言能力和工程开发体验都往前推了一大步。如果让我概括,C++98 更像传统 C with class,C++11 开始才真正进入现代 C++ 的阶段。

代码:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> nums = {1, 2, 3, 4};
    for (auto x : nums) {
        cout << x << " ";
    }
    cout << endl;

    auto add = [](int a, int b) { return a + b; };
    cout << add(3, 4) << endl;
    return 0;
}

8. 智能指针你介绍一下

如果按现在实际开发的角度来说,我会重点讲 unique_ptrshared_ptrweak_ptrunique_ptr 表示独占所有权,同一时间只能有一个指针拥有对象,不能拷贝,可以移动,适合明确资源归属的场景。shared_ptr 是共享所有权,通过引用计数来管理对象生命周期,只要还有一个强引用存在,对象就不会被释放。它适合多个对象共同持有一份资源的场景。weak_ptr 不拥有对象,只是观察 shared_ptr 管理的资源,主要用途是打破循环引用,或者在使用前先判断对象是否还存活。至于 auto_ptr,它是早期标准里的产物,拷贝时会转移所有权,语义很危险,后来已经被废弃了。循环引用是 shared_ptr 很典型的问题,比如 A 持有 B,B 又持有 A,两个对象的引用计数都不会归零,这时候就需要一边改成 weak_ptr

代码:

#include <iostream>
#include <memory>
using namespace std;

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

C++ 常考面试题总结 文章被收录于专栏

本专栏系统梳理C++方向, 大中厂高频高频面试考点 , 内容皆来自真实面试经历,从基础语法、内存管理、STL与设计模式,到操作系统与项目实战,结合真实面试题深度解析,帮助开发者高效查漏补缺,提升技术理解与面试通过率,打造扎实的C++工程能力.

全部评论

相关推荐

03-11 20:19
已编辑
门头沟学院 Java
太压力了,面了2个多小时,本菜比已经被拷打的瑟瑟发抖面完两个小时后通知过了1.算法题三道(1)leetcode124&nbsp;二叉树中最大路径和hard题&nbsp;因为不久前才刷过撕出来了,又来了一道(2)leetcode&nbsp;300&nbsp;最长递增子序列变种除了递增之外还加了一个权重因素,但是思路没变,dp就行(3)寻找词汇库里符合固定长度前缀的匹配单词应该是他们自己题库的题。给了一串单词列表,然后又给了一个单词,一个下标,根据这个下标的前缀去单词列表里面找到所有匹配的单词再返回思路是创建一个单词前缀树,然后根据树找,但是可能是构件树数有问题没撕出来2.全方位项目拷打基本没有问八股,全部都是项目企业场景题,哎哟我操,完全不会。我就纯八股战士,结果没想到一道八股都没问反正尽可能把企业场景往八股上引吧。。1.&nbsp;微服务多点部署其中一个宕机了怎么办2.&nbsp;要是mq占据大量CPU该怎么排查?MySQL占据大量CPU该怎么排查?3.&nbsp;假如说让你实现视频点赞功能,你打算怎么设计?讲讲思路(我知道多级缓存,但是碰巧没背……寄)4.&nbsp;Redis延迟双删是什么,分布式锁,哨兵模式5.&nbsp;MySQL到es同步的延迟该怎么优化6.&nbsp;Rabbit&nbsp;mq的队列是怎么实现的?(这个完全没整明白,可能是队列的底层结构?&nbsp;反正我硬扯的讲了一下rabbit&nbsp;mq的架构)还扯了很多,但是往后完全就慌了),记住的是这些
不知道怎么取名字_:2小时确实有压力,持续性的脑力劳动啊
查看9道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务