蚂蚁 C++开发 一面

1. 自我介绍

2. 讲一下你做过的项目,重点说说其中最难的技术点

3. 我看你实习了一年了 怎么没留在上家公司

4. 说一下线程、进程、协程的区别,如果放到你的项目里会怎么选

答案:进程是资源隔离单位,线程是 CPU 调度单位,协程更像用户态轻量执行流。进程的隔离性最好,但切换和通信成本更高;线程共享地址空间,适合同一个服务内并行处理任务,但要处理锁竞争和共享数据一致性;协程切换开销小,特别适合高并发 I/O 等待场景。如果放到服务端项目里,我通常会让网络接入层偏事件驱动或协程化,避免大量阻塞线程;真正的 CPU 密集型计算,比如压缩、解析、聚合,会放到线程池里做。所以不是三选一,而是看场景组合使用。

5. 线程同步有哪些手段,互斥锁、读写锁、条件变量分别适合什么场景

答案:互斥锁适合保护共享资源的修改,语义最直接,也是最常用的。读写锁适合读多写少的场景,可以允许多个读线程并发进入,但写线程要独占。条件变量适合线程间通知,比如生产者放入任务后唤醒消费者,不适合单纯拿来做互斥。如果只是计数器、状态位这种简单共享数据,原子操作会比大锁更轻。工程里真正要注意的是临界区长度和共享粒度,锁本身只是工具,设计共享数据的方式往往比“选哪把锁”更关键。

代码:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
using namespace std;

mutex mtx;
condition_variable cv;
queue<int> tasks;
bool stopFlag = false;

void worker() {
    while (true) {
        unique_lock<mutex> lock(mtx);
        cv.wait(lock, [] { return !tasks.empty() || stopFlag; });
        if (stopFlag && tasks.empty()) break;
        int x = tasks.front();
        tasks.pop();
        lock.unlock();
        cout << "process task: " << x << endl;
    }
}

6. C++ 里 new/delete 和 malloc/free 的区别是什么

答案:malloc/free 是 C 风格内存管理,分配的是原始字节块,不会调用构造和析构。new/delete 是 C++ 运算符,除了分配内存,还会调用对象的构造函数和析构函数。所以对于普通 POD 类型,有些时候看起来都能用,但对类对象来说语义差别非常大。另外 new 失败时默认抛异常,malloc 失败时返回 NULL。底层上它们都可能走到同一套分配器,但语言层面的对象生命周期管理完全不是一回事,不能混用。

7. 说一下 C++ 的虚函数、多态以及虚表一般是怎么实现的

答案:多态通常依赖虚函数实现。父类声明虚函数后,子类重写它,通过父类指针或引用调用时,实际执行哪个函数会在运行期决定。主流编译器实现里,带虚函数的对象通常会有一个隐藏的虚表指针 vptr,它指向该类型对应的虚函数表。调用虚函数时,程序先通过 vptr 找到虚表,再定位真正的函数入口。虚函数代码本身不在对象里,对象里一般只是多了一个指针。如果涉及多继承和虚继承,布局会复杂很多,因为编译器还要处理基类偏移和对象调整。

8. map 和 unordered_map 有什么区别,线上怎么选

map 通常基于红黑树实现,键有序,查找、插入、删除是 O(log n)unordered_map 通常基于哈希表实现,键无序,平均复杂度接近 O(1)。如果业务需要有序遍历、范围查询、lower_bound 这类能力,选 map 更自然。如果业务更看重单点查找性能,且不要求顺序,通常优先 unordered_map。线上选型时我还会看 key 分布是否容易冲突、内存占用是否敏感、扩容 rehash 是否可接受,因为哈希表在极端情况下性能也会退化。

9. 说一下 mmap 和 read/write 的区别,什么时候更适合用 mmap

答案:read/write 是显式把数据从内核缓冲区拷到用户缓冲区,程序自己控制读写过程。mmap 是把文件映射到进程虚拟地址空间,访问文件内容更像直接访问内存。mmap 的优势是减少了一层显式拷贝,随机访问大文件会比较自然,也适合多个进程共享映射区域。但它也不是银弹,页面缺失、写回时机、地址空间占用、访问局部性差时的抖动都要考虑。如果是顺序流式读取,read 往往更直观;如果是大文件随机访问或需要共享映射,mmap 更有优势。

10. 你怎么理解零拷贝,它真的完全没有拷贝吗

零拷贝的核心目标是减少 CPU 参与的数据复制次数,降低上下文切换和内存带宽消耗。像 sendfilemmap + write、DMA 这

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

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

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

全部评论

相关推荐

04-04 21:23
门头沟学院 Java
一直没有勇气书写下书写下这段时间的找实习经历一直在焦虑也一直在碰壁,但是不可否认的是在经历各种碰壁之后自己反而成长的最快首先是一开始的中小型公司,聊的都挺好的,也都愿意发offer一个一个首先介绍吧首先万兴科技这是我觉得非常恶心的一个公司(不刻意抹黑,我只说事实),实际上只有一轮技术面试,后面两轮问的比较少,但是他们是Golang需要转语言,星期三业务部的领导面过之后答应可以入职,跟hr联系之后答应是下周三之前给他们答复,到我周二想详细的了解薪资跟培养制度以及转正,当时hr跟我说的是问一下业务部给我订的职级,hr准备实际的发邮箱offer了,一个小时之后hr跟我说他们业务部早就终止流程,连hr都不知道,属实有点恶心人然后的话就是字节海外电商,一路面到了第四轮技术终面,解释一下为什么有四轮,因为第二轮的算法题面试官让我用最优解写出来,面试官也一直跟我将思路,但是当时没get到核心,没写出来,所以又加了一轮面试,技术终面推迟了两次,每次都是面试前一个小时告诉我面试官临时有事,上来让我用IDE写题,一道字符串操作题,一开始用正则表达式几分钟就写好了,后面又让我自己实现,写完没考虑特殊情况,面试官说知道了直接开始面试,上来就是场景题,一百亿条IP加时间戳的日志数据内存限制100M,统计IP出现次数并且实现排序,我的思路是先对文件进行分片,对日志进行hash取模之后相同IP放到同一个分片文件中,再对小文件内进行IP统计和排序,最后的话就是多路归并排序写入到文件中,后来就是问我高考分数,还有一些八股,其中的话https加密握手聊挺长,我只详细说了RSA机制的握手加密面试官可能不是太熟悉一直问我是这样的吗,一直在追问为什么双方要进行随机数交换还有预主密钥跟他详细解释之后面试官也觉得我说的挺好的,自己就是安全专业的所以对这个使用非对称加密实现对称加密秘钥传输比较熟悉,最后应该是排序挂,那边有更好的人选,第二天又被其他部门捞起来了(贴个手撕:带超时的LRU,最小覆盖子串,下一个排序,最大有效括号长度,版本号比较,编辑距离变种)小米hr联系的时候进行了二十多分钟AI相关知识的问答,联系一面,面试体验比较好,面试官比较实在,直接说八股列表找两个问我,手撕环节是让我搭建一个后端服务简单的进行CRUD可以使用AI,面试时长一个多小时,后面的话面试结果不知道,给Hr打电话也不接应该是KPI腾讯直接没有面试,已经找过校园大使HR帮忙投递但是一直没面,身边的人都给面了就我没有,可能是之前提前批自己的处男面面评不太好,鼠鼠也是无奈啊快手简历挂,米哈游简历挂其他像华为阿里实习开的比较晚,因为自己手上有offer,并且自己还能接受,所以就没面了美团是实习之后面的,一直没时间准备,答的还行,但是因为美团面试平台有问题,没手撕只说了思路题目不难leetcode中的课程表那道题自己没详细整理面经,只是记录每次面试中答的不太好的,所以这里就不贴面经了最后的话选择了一家中小厂吧,还是不透露了呜呜呜,公司发的mac还用的不太习惯,但是AI模型随便用,我一周就用了三十刀,mentor是个大牛也是个老顽童贼有趣,实习体验挺好入职一周多,自己随便写的心得大家不要嫌弃
查看10道真题和解析
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

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