360 客户端开发 一面(暑期)

1. 自我介绍

2. 详细讲一下实习工作的内容

3. 为什么一般说 RPC 性能优于 HTTP

答案:严格来说,不能简单地说 RPC 一定优于 HTTP,更准确的说法是很多 RPC 框架在内部服务调用场景下通常比传统 HTTP/1.1 + 文本协议更高效。原因主要在于协议更轻、序列化更紧凑、连接复用更充分、接口定义更明确。很多 RPC 框架会使用 Protobuf 这类二进制序列化格式,相比 JSON 体积更小、解析更快;同时内部调用路径往往不需要那么多通用语义字段,报文开销更低。另外,RPC 框架通常把服务发现、负载均衡、超时控制、重试、熔断、链路追踪这些能力整合进去了,所以在工程上也更适合服务间高频通信。但如果是对外开放接口、浏览器友好性、跨语言和生态兼容,HTTP 仍然非常有优势。

4. Linux 下你一般怎么监控性能指标

答案:先看 CPU、内存、磁盘 IO、网络带宽和上下文切换这几个基础指标。CPU 常用 topmpstatpidstat 看整体利用率和单进程消耗;内存可以用 freevmstatsmem;磁盘 IO 常用 iostatiotop;网络用 sar -n DEVssnetstat;如果怀疑有热点函数或锁竞争,会进一步用 perf 做采样。真正线上排查不会只看机器整体,还要结合进程、线程、连接数、队列积压和日志延迟一起看,不然很容易只看到表象。

代码:

top
mpstat -P ALL 1
pidstat -p 1234 1
vmstat 1
iostat -x 1
sar -n DEV 1
ss -s
perf top -p 1234

5. 怎么定位和排查内存泄漏,常用什么工具

答案:先区分是内存泄漏,还是缓存膨胀、连接堆积、对象池不释放导致的常驻内存增长。如果怀疑是真泄漏,本地调试时可以直接用 AddressSanitizer、Valgrind、LeakSanitizer 这类工具;线上如果不方便上重工具,就先加对象数量、队列长度、连接数、缓存命中率这类指标,看看是不是某类资源持续积压。C++ 服务里常见问题包括 shared_ptr 循环引用、容器只增不减、任务队列消费跟不上、异常路径没释放资源、线程本地对象长期占用等。排查时最好结合时间维度看增长速率,再回溯到最近发布的模块和调用链。

代码:

g++ -fsanitize=address -g main.cpp -o app
./app

valgrind --leak-check=full --show-leak-kinds=all ./app

6. 指针和引用的区别

答案:引用本质上是一个已存在对象的别名,语义上更像“这个名字就是那个对象”;指针本质上是一个变量,里面存的是地址。引用定义时必须初始化,通常不能重新绑定;指针可以为空,也可以在不同时间指向不同对象。从使用上看,引用更适合表达“这个参数一定有效,而且函数内部只是操作原对象”;指针则更适合表达“这个对象可能不存在”或者“需要显式管理地址”。底层实现上编译器可以把引用实现成指针,但语言语义上两者不是一回事。

代码:

#include <iostream>
using namespace std;

int main() {
    int a = 10, b = 20;
    int* p = &a;
    int& r = a;

    p = &b;
    r = b;

    cout << *p << endl;
    cout << r << endl;
    return 0;
}

7. 堆和栈的区别

答案:栈主要存函数调用相关的信息,比如局部变量、返回地址、参数和寄存器现场,分配释放由编译器和调用过程自动完成,速度快,但空间通常比较有限。堆是程序运行时动态申请的大块内存区域,生命周期由程序员或运行时决定,灵活性更强,但分配释放成本更高,也更容易产生碎片和泄漏。如果面试官继续问,一般还会追栈溢出、堆碎片、内存分配器和线程栈空间这些问题。

8. static 关键字的作用

答案:static 修饰局部变量时,表示它只初始化一次,但作用域还在原来的代码块里;修饰全局变量或函数时,表示它们只在当前编译单元可见;修饰类成员变量时,表示它属于整个类而不是某个对象;修饰类成员函数时,表示这个函数没有 this 指针。这题本身不难,但延伸出去很容易问到静态局部变量线程安全、静态初始化顺序和单例实现。

代码:

#include <iostream>
using namespace std;

class A {
public:
    static int cnt;
    A() { ++cnt; }
};

int A::cnt = 0;

int main() {
    A a, b;
    cout << A::cnt << endl;
    return 0;
}

9. 死锁的必要条件是什么

答案:死锁一般满足四个必要条件:互斥、请求与保持、不可剥夺、循环等待。互斥指资源一次只能被一个执行单元占用;请求与保持指已经持有部分资源的线程还在继续请求新资源;不可剥夺指资源不能被强制拿走;循环等待指多个线程之间形成了资源依赖环。避免死锁最常见的方法是统一加锁顺序、尽量缩小锁粒度、使用 try_lock 或带超时的锁,以及在设计阶段避免多把锁交叉持有。

10. 进程和线程的区别,线程奔溃后在进程视角会发生什么

答案:进程是资源分配的基本单位,线程是

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

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

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

全部评论
可以的,写的很好
点赞 回复 分享
发布于 04-19 23:08 北京

相关推荐

我面的是Golang后端,结果上来基本上不问后端问题,全问的是AI方向的,也不问简历,什么Go协程,并发,GMP调度和大部分是数据结构底层八股全部都不问,还有后台常考的Mysql,Redis和MQ也不问。问了大模型落地训练微调量化,还有FunctionCalling,MCP,龙虾Skill。出了两个简单的计算题有一个结果还出错了,我推导半天结果有问题,最后拿编译器穷举发现根本没结果。最后问为什么不问后端题目而是问AI方向的,回答是因为我简历里面的项目全是保密项目,技术难点不可能达不到真实业务高并发需求,所有的实现都是基于标书的,所以问了等于没问,索性就不问了。面完之后感觉人都麻了,感觉就是不想面,还不如直接说出来拒接,浪费双方的时间。题目:abc+cba=1331,求解a+b+c=?我的解法是:100a+10b+c+100c+10b+a=1331101a+20b+101c=1331101(a+c)=1331-20b令a+c=x∈0-18,b=y∈0-9101x=1331-20y右边y的系数是20,所以不管怎么减右边个位数都是1,那么左边101只能乘个位数为1的数也就是x要么是1要么是11,但是1和11的时候y都不满足条件0-9然后我人麻木了陷入了怀疑,就拿编译器用穷举(三重for循环实现)package&nbsp;mainimport&nbsp;&quot;fmt&quot;func&nbsp;main()&nbsp;{for&nbsp;a&nbsp;:=&nbsp;0;&nbsp;a&nbsp;&lt;&nbsp;10;&nbsp;a++&nbsp;{for&nbsp;b&nbsp;:=&nbsp;0;&nbsp;b&nbsp;&lt;&nbsp;10;&nbsp;b++&nbsp;{for&nbsp;c&nbsp;:=&nbsp;0;&nbsp;c&nbsp;&lt;&nbsp;10;&nbsp;c++&nbsp;{if&nbsp;101*(a+c)+20*b&nbsp;==&nbsp;1331&nbsp;{fmt.Println(a&nbsp;+&nbsp;b&nbsp;+&nbsp;c)fmt.Printf(&quot;a:&nbsp;%d,&nbsp;b:&nbsp;%d,&nbsp;c:&nbsp;%d\n&quot;,&nbsp;a,&nbsp;b,&nbsp;c)}}}}}最后结果也是没有输出,最后面试官才反应过来是1131算了半天结果是题目有问题
查看6道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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