招银网络科技 C++ 后端一面:多态虚函数表与合并有序数组
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 介绍一下你项目的亮点
- C++ 的多态是怎么实现的?
- 虚函数表是什么?
- 虚函数表存在哪里?
- 动态库的加载位置?
- C++ 的内存模型是怎样的?
- TCP 粘包怎么处理?
- 手撕:有两个升序数组 a 和 b,长度分别是 m 和 n,数组 a 有 m+n 个格子,把 b 合并到 a 里并保持 a 升序
《参考解析》
-
合并有序数组要从后往前写,这是本题唯一的考点:a 的尾部已经留好了空间,正着写会把还没比较的元素覆盖掉。用三个指针
i = m-1、j = n-1、k = m+n-1,每次把a[i]与b[j]中较大的放到a[k],再各自左移;循环结束时如果 b 还有剩余就直接拷到 a 的前面(a 有剩余则不用动)。复杂度 O(m+n) 时间、O(1) 空间。现场手撕容易挂的两个细节:循环条件写的是j >= 0而不是i >= 0,以及把「m 是有效元素个数、不是数组容量」这件事在开场就跟面试官确认一遍。 -
虚函数表存在哪,标准没规定,实现上通常在只读数据段:编译器为每个「有虚函数的类」生成一张 vtable,里面是虚函数的地址;对象里只多存一个 vptr 指向它,所以同一类的所有对象共享同一张表。常见的落点是
.rodata/.data.rel.ro(重定位只读段),属于模块级别的静态数据,不在堆也不在栈上。被追问「多继承/虚继承呢」可以答:多继承会有多张 vtable 和多个 vptr,虚继承还要靠虚基类表来定位基类子对象。 -
动态库涉及「文件在磁盘」和「映射进虚拟地址空间」两件事,答的时候分开说:
.so文件本身放在磁盘路径(如/lib/x86_64-linux-gnu、或者构建产物目录),由动态链接器在程序启动时按RPATH/LD_LIBRARY_PATH//etc/ld.so.cache的优先级查找;找到后 mmap 到进程的用户态虚拟地址空间,代码段映射为只读可执行、数据段按需映射,多个进程还能共享同一份物理页。跟静态库对比着说更能显出理解:动态库省内存、可独立升级,代价是启动时的符号解析开销和版本兼容问题。 -
「C++ 的内存模型」是一句歧义词,先确认对方问的是哪层:一层是内存布局,代码段、只读常量、全局/静态区、堆、栈,以及线程各自的栈;另一层是语言标准里的 memory model——happens-before 关系、原子操作与内存序(
memory_order_relaxed到seq_cst)、编译器与 CPU 的重排序约束。面试里先说清自己答的是哪一层,再各讲两三句,比闷头背内存分区要稳。顺带能把volatile不等于同步原语这个坑点出来。 -
TCP 粘包本质是「字节流没有消息边界」,所以解法全在应用层协议:定长消息、分隔符(如
\r\n)、或者最常用的「长度字段 + 消息体」(TLV / 变长头)。工程上还要补几句:拆包时缓冲区要处理「半个包头」和「半个包体」两种中间态;设最大包长防止恶意超长字段;如果用 Netty 这类框架,考点会落到LengthFieldBasedFrameDecoder的参数语义上。反过来答「TCP 会粘包所以要设置 TCP_NODELAY」是常见失分点——TCP_NODELAY关的是 Nagle 算法,跟粘包不是一回事。