面灵AI→

金证股份 C++ 开发工程师面试

轮次
技术面
时间
2026-10
来源
牛客网

《面试题目》

  1. 请做一下自我介绍。
  2. 介绍简历上的项目。
  3. epoll 和 select 有什么区别?
  4. epoll 的 ET 模式为什么要求非阻塞 Socket?一次 EPOLLIN 后应该读到什么程度?
  5. 重载和重写有什么区别?
  6. C++ 函数返回大型 vector 时发生拷贝还是移动?为什么有时写 std::move 反而更慢?
  7. Linux 进程间通信有哪些方式?
  8. 共享内存为什么通常比 Socket IPC 快?设计共享内存 RingBuffer 要解决哪些问题?
  9. vector 的底层实现是什么?

《参考解析》

select 每次调用都要把 fd 集合传入内核,返回后用户态还要遍历,且有 FD_SETSIZE 限制;epoll 通过 epoll_ctl 注册,epoll_wait 只返回就绪事件,适合大量连接、少量活跃的场景。但不能简单说 epoll 是 O(1),活跃连接很多时业务处理成本仍然存在。

ET 是边沿触发,只在状态变化时通知。收到 EPOLLIN 后要循环读到 EAGAIN,否则缓冲区剩余数据可能不再触发新事件;因此 Socket 必须是非阻塞,避免阻塞事件循环。写事件同理,发送缓冲区满时注册 EPOLLOUT,写完及时取消。

返回局部 vector 时,编译器可以通过 RVO/NRVO 直接在目标位置构造,写 return std::move(v) 可能阻止 NRVO,反而多一次移动。移动构造通常接管指针,但不是所有类型都能做到 O(1)。共享内存 RingBuffer 要解决消息边界、读写索引的原子发布、内存序、False Sharing、满队列策略和进程崩溃恢复。