微派 c++软件开发 一面 面经

1. 堆和栈的区别是什么?

  • 栈由编译器自动管理,存放局部变量、函数参数、返回地址,空间有限(一般几 MB),分配和释放速度极快
  • 堆由程序员手动管理,通过 malloc/new 申请,空间大(受物理内存限制),但分配释放开销更大
  • 栈是连续内存,向低地址增长;堆是离散内存,由内存分配器管理
  • 栈上的对象生命周期随函数结束自动销毁;堆上的对象需要显式释放,否则造成内存泄漏

2. TCP 三次握手的过程是什么?为什么不能是两次?

过程:

  • 第一次:客户端发送 SYN,进入 SYN_SENT 状态
  • 第二次:服务端收到后回复 SYN+ACK,进入 SYN_RCVD 状态
  • 第三次:客户端回复 ACK,双方进入 ESTABLISHED 状态

为什么不能是两次:

  • 两次握手只能确认客户端到服务端的通路正常,无法确认服务端到客户端方向
  • 三次握手让双方都能确认自己的发送和接收能力均正常
  • 同时可以防止历史失效的连接请求被服务端误认为新连接,造成资源浪费

3. malloc 的底层实现机制是什么?

  • 小块内存(通常 < 128KB):通过 brk/sbrk 系统调用移动堆顶指针扩展堆空间,glibc 内部用空闲链表(bin)管理,减少系统调用次数
  • 大块内存(>= 128KB):通过 mmap 直接映射匿名内存,释放时 munmap 归还操作系统
  • 内部按大小维护多个 bin,分配时优先从合适的 bin 中复用空闲块,找不到再向 OS 申请
  • 频繁分配释放不同大小的内存会产生内存碎片,是 malloc 的主要问题之一

4. 有 1 万个下载任务,单进程如何合理分配线程数?

  • 下载属于 I/O 密集型任务,线程大部分时间在等待网络响应,CPU 占用低
  • 线程数不是越多越好,过多会导致内存占用高(每个线程默认栈约 1~8MB)、上下文切换频繁
  • 经验公式:线程数 = CPU 核心数 × (1 + 等待时间 / 计算时间),I/O 密集型可适当放大倍数
  • 实际做法是用线程池(如 100~500 个线程)配合任务队列,1 万个任务排队分批消费
  • 更优方案是异步 I/O(epoll + 协程),用少量线程处理大量并发,避免线程膨胀

5. 进程间通信有哪些方式?各自适用场景是什么?

  • 管道(pipe):适合父子进程间单向通信,简单但只能传字节流
  • 消息队列:支持结构化消息,解耦发送和接收方

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

C++八股文全集 文章被收录于专栏

本专栏系统梳理C++技术面试核心考点,涵盖语言基础、面向对象、内存管理、STL容器、模板编程及经典算法。从引用指针、虚函数表、智能指针等底层原理,到继承多态、运算符重载等OOP特性从const、static、inline等关键字辨析,到动态规划、KMP算法、并查集等手写实现。每个知识点以面试答题形式呈现,注重原理阐述而非冗长代码,帮助你快速构建完整知识体系,从容应对面试官提问,顺利拿下offer。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

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