面试 · 实战合集

Posted by Kang Cai on August 23, 2020

语言

1. python 装饰器写一个,装饰器的原理

2. python 垃圾回收:引用计数 + 标记清除、分代收集(链表实现)

3. C++ 多态,虚函数:虚函数继承是解决多态性的,当用基类指针指向派生类对象的时候,基类指针调用虚函数的时候会自动调用派生类的虚函数,这就是多态性,也叫动态编联。重要概念是 虚函数指针(vfptr) 和 虚函数表(vftable)。虚函数表在编译的时候就确定了,而类对象的虚函数指针vfptr是在运行阶段确定的,通过使 vfptr 指向不同的 vftable 实现的多态。

4. C++中,构造函数能定义为虚函数吗? 虚函数相应一个指向vtable虚函数表的指针,但是这个指向vtable的指针事实上是存储在对象的内存空间的。假设构造函数是虚的,就须要通过 vtable来调用,但是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数。

5. C++ 虚函数(virtual)能是static的吗? 不能,因为静态成员函数可以不通过对象来调用,即没有隐藏的this指针;而virtual函数一定要通过对象来调用,即有隐藏的this指针

6. C++ 某个类有继承时,这个类的析构函数必须为虚函数吗? 是的,如果不是虚函数,则使用时可能存在内在泄漏的问题。基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了基类的资源,而没有调用继承类的析构函数。

7. C++ 纯虚函数是什么?有办法能调用纯虚函数吗? 纯虚函数意味着它没有函数的实现,需要让派生类去实现。能调用纯虚函数,通过静态调用即可。

8. C++ 抽象类?抽象类的继承类不实现纯虚函数会怎样? 声明了纯虚函数的类,都成为抽象类,抽象类只能作为基类来派生新类,不能声明抽象类的对象。抽象类的继承类不实现纯虚函数,那么继承类本身也是抽象类,不能直接用来实例化对象。

9. 菱形普通继承写法有什么问题?编译能通过吗?

10. 虚继承是什么? 虚继承主要用于菱形形式的继承形式,是为了在多继承的时候避免引发歧义,避免重复拷贝。重要概念是 虚基类指针(vbptr)虚基类表(vftable)

11. 虚继承实例 A{int, double} B:A{int} C:A{int} D{int}。普通继承 16, 24, 24, 56; 虚继承 16, 24, 24, 40

12. static的用法 类外、类内,初始化

13. const_cast、static_cast、dynamic_cast、reinterpret_cast

14. dynamic_cast 为何要求转换的基类要有虚函数? 这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表中,只有定义了虚函数的类才有虚函数表,没有定义虚函数的类是没有虚函数表的。

操作系统

1. 虚拟内存是什么?虚拟内存的原理?虚拟内存的作用? 缓存、一致(为每个进程提供了一致的地址空间,简化内存管理)、利用分散内存、内存保护(保护了每个进程的地址空间不被其他进程破坏)。页表->物理存储器和虚拟存储器。

2. 虚拟内存具体是如何与物理内存联系的? 通过页表,页表就是一个页表条目(Page Table Entry,PTE)的数组,每个PTE由一个有效位(valid bit)和一个地址组成,有效位表明了该虚拟页当前是否存在于物理内存中:1.如果有效位是1,该PTE中就会存储物理内存中相应的物理页的起始地址;2.如果有效位是0,且PTE中的地址为null,这表示这个虚拟页还未被分配;3.如果有效位是0且PTE中有地址,那么这个地址指向该虚拟页在磁盘上的起始位置

3. 多个虚拟页面可以映射到同一个物理页面上吗?(共享页面) 就是所谓的共享内存。

4. 不考虑共享内存,Linux下运行在用户态的两个进程,进程可以修改其它进程的内存吗?Windows是否可以? Linux 可以,典型方法 ptrace、process_vm_writev;Windows 也可以,典型方法 WriteProcessMemory

5. 进程和线程的区别?

6. 进程间通信方式管道、消息队列、共享内存、信号量、socket套接字。

7. 不同系统不同语言,如何交互? WebService,Http请求。WebService,即“Web 服务”;常见的不同系统相同语言之间的交互用RPC(Remote Procedure Call, 远程过程调用),或者RMI(远程方法调用)实现,不用对外部提供服务,RPC也可以用于不同语言之间的交互,但需要多一个翻译步骤。

网络编程

1. TCP 协议建立连接的过程? 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。完成三次握手,客户端与服务器开始传送数据

2. TCP和UDP的区别? 1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接;2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。3、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。4.每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。5、TCP对系统资源要求较多,UDP对系统资源要求较少。

3. TCP拥塞控制算法? 慢启动、拥塞避免、快速重传、快速恢复。

4. 为什么UDP有时比TCP更有优势? 1. 网速的提升给UDP的稳定性提供可靠网络保障,丢包率很低,如果使用应用层重传,能够确保传输的可靠性。(2)TCP为了实现网络通信的可靠性,使用了复杂的拥塞控制算法,建立了繁琐的握手过程,由于TCP内置的系统协议栈中,极难对其进行改进。采用TCP,一旦发生丢包,TCP会将后续的包缓存起来,等前面的包重传并接收到后再继续发送,延时会越来越大,基于UDP对实时性要求较为严格的情况下,采用自定义重传机制,能够把丢包产生的延迟降到最低,尽量减少网络问题对游戏性造成影响。

5. UDP 如何实现可靠性传输? UDP 它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用 UDP 较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照 TCP 可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。

6. 应用场景。普通会议视频用什么?传输文件? 会议视频用 UDP;传输文件用 TCP。

7. HTTP 与 TCP 的联系。TCP是底层通讯协议,定义的是数据传输和连接方式的规范;HTTP是应用层协议,定义的是传输数据的内容的规范;HTTP协议中的数据是利用TCP协议传输的,所以支持HTTP也就一定支持TCP。

8. 客户端与服务端网络通信流程。 客户端创建 socket -> 连接 server(connect) -> 收发数据;服务端创建 socket -> 绑定 ip 和 端口号(bind) -> 启动侦听(listen) -> 接受客户端连接(accept) -> 与客户端通信收发数据。其中服务端首先进行 bind,listen,accept 后进行阻塞,然后客户端的 connect 阻塞客户端,主动开启三次握手,客户端收到服务端发下来的第二次握手时 connect 就返回了,并且发送第三次握手的 ack 给服务端,服务端 accept 返回,并调用 read,再次阻塞。如果服务端不写 accept,客户端能成功与服务端进行三次握手吗?可以,accept 就是从监听队列里取节点,每个节点都是已经完成了三次握手的。

算法

1. 2sum,考虑不重复(E)、重复(M)、3sum问题(M)

2. 最长递增子序列,考虑动态规划(M)、二分优化(H)、空间省略(H)

3. 代码实现二叉树的中序遍历,打印出来即可:递归、非递归,struct Node {int val; Node *left, *right;}

4. N 个绳子和对应的长度数组 L,要求截取 K 段长度相等的绳子段,求绳子段最长长度可以是多少,二分

数据结构

1. LRU 链表+Hash

2. 4 O(1)数据结构,增加、修改、删除、随机取 数组+Hash

开放题

1. 千人同屏放技能问题。 考虑 暴力、KD-Tree、AOI、map

2. 在1M内存中,对将近一千万条不同的整型数据流进行排序,并且数字大小不超过1000万 每个数字用4byte,1M即可存储250000个数据,显然,只要每次对250000个数据排序,写入到文件中即可,重复40次。 归并,每次选出一个(M)位运算 a[i » 5] | (1 « (i%32)); (H)