说一下TCP协议
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP在数据传输前需要建立连接,通过三次握手过程来建立连接,四次握手断开链接确保数据传输的可靠性。TCP通过序列号和确认应答机制来确保数据包的正确传输,如果数据包在传输过程中丢失或出错,TCP会重新发送丢失的数据包。TCP使用滑动窗口机制来控制发送方的数据流量,以适应接收方的处理能力。广泛应用于各种网络应用中,如Web浏览器、电子邮件、文件传输等
常用的进程通信
管道、消息队列、信号、共享内存、套接字、信号量、文件映射、条件变量等
介绍一下cmake
CMake是一个跨平台的自动化构建系统,它用一个叫做CMakeLists.txt的文件来描述项目的构建过程。这个文件里,你可以定义项目如何编译,需要哪些源文件,链接哪些库,以及设置各种编译选项。不管你是在Windows、Linux还是Mac上,CMake都能帮你搞定编译。你可以写自己的CMake模块来扩展功能,或者用现成的模块。在命令行里,你运行CMake,它会根据CMakeLists.txt生成一个Makefile或者相应的项目文件。生成了Makefile之后,你就可以用它来编译项目了。
C++的异常
在程序的执行过程中,可能会遇到各种预料之外的情况,比如无效的输入、资源不足、或者操作失败等。如果没有妥善的异常处理机制,这些意外情况可能会导致程序崩溃或者产生不可预测的行为。
- 抛出异常:当你的代码遇到了一个它处理不了的情况,你可以用
throw关键字抛出一个异常。这就像是你考试时遇到不会的题,你把这个问题“扔”给了监考老师。 - 捕获异常:就像你考试时老师会帮你解决问题一样,你的程序也可以用
try块来尝试执行一些可能会抛出异常的代码,然后用catch块来“捕获”这些异常,并给出相应的处理。 - 标准异常:C++标准库提供了一些内置的异常类型,比如
std::runtime_error或std::logic_error,这些就像是考试中的常见题型,你至少得知道怎么应对。 - 自定义异常:如果你觉得标准异常不够用,你也可以自己定义异常类型,这就像是你为了应对考试,自己总结了一些解题模板。虽然C++11已经弃用了异常规范,但在旧代码中可能还会遇到。了解它们可以帮助我们更好地理解和维护这些代码。
在windows调用Linux系统命令,与linux通信,有一个C语言实现的函数要调用shell的命令,比如说"top"cpu的占用,如何通过调用一个命令来拿到top执行的结果
- 如果你有一个远程的Linux系统,你可以通过SSH连接到该系统并执行命令。在C程序中,你可以使用库如
libssh来实现SSH连接和命令执行。 - 或者使用系统调用,在C语言中,你可以使用
system函数或者popen函数来调用命令行命令。但是,这些函数在Windows上调用Linux命令是无效的,因为Windows没有内置的Linux命令。
内敛函数
内敛函数,也叫内联函数(Inline Function),是C++中的一个特性。它是一种特殊的函数,编译器在编译时会直接将函数的代码嵌入到每个调用该函数的地方,而不是生成函数调用的代码。这就像是把函数的"源代码"复制粘贴到调用点,而不是生成额外的跳转指令,就像使用快捷键一样,省去了函数调用的开销,内敛函数可以提高程序的执行效率,特别是在函数体较小且调用频繁的情况下。由于没有实际的函数调用,也就不会有压栈和弹栈的操作,这在一定程度上可以避免栈溢出的问题。下面是一个内敛函数的例子
inline int add(int a, int b) { return a + b; }
宏定义一个函数,这个函数有很多行,怎么保证每一行的函数都能执行,通过怎么样的宏定义去保证每一行函数都能执行,每一行里面有很多逻辑,有很多子函数
1.使用do { ... } while (0)技巧:这可以确保宏定义在一个语句块中执行,同时避免了多余的分号问题。
2.使用多行字符串:把每行逻辑放在一个字符串里,然后用\来连接它们。
#define COMPLEX_MACRO(x) do { \
int temp = (x) + 1; \
if (temp > 10) { \
temp *= 2; \
} \
return temp; \
} while (0)
宏定义和const去定义参数有什么区别
宏定义是通过#define指令实现的,它在预处理阶段就被替换成你定义的内容。就像是个文本替换工具,不管你定义的是变量还是复杂的表达式,编译器在编译前就把它们全换了。而const定义则是在编译时期就确定了值,它是有数据类型的,并且在内存中占有空间。使用const定义的参数,你可以利用编译器的各种优化,而且类型安全,还能享受调试的好处。
迪杰斯特拉是广度有限还是深度有限
广度
怎么检测一个图中是否存在环
- 深度优先搜索(DFS) 想象一下,你在一个迷宫里,用笔在墙上做标记。如果你在走的过程中,又回到了一个已经做过标记的地方,而且这个地方不是你刚离开的地方,那就意味着你找到了一个环。
- 并查集 并查集就像是你的朋友圈,每个人要么自己是一个朋友圈的中心,要么就属于别人的朋友圈。如果两个朋友圈的中心发现他们其实是同一个朋友圈的,那就意味着他们之间有环。
- 拓扑排序 拓扑排序就像是给你的课程表排序,每门课都只能在它的先修课之后上。如果在排序过程中,你发现一门课的先修课还在它后面,那就意味着课程表里有环。
介绍一下linux的内存管理还有他是怎么从一个逻辑地址映射到一个物理地址的
- 物理内存(RAM) :这是你的电脑实际拥有的内存,就像你钱包里的现金一样,是直接可用的资源。
- 虚拟内存:Linux使用虚拟内存来扩展可用的内存空间,通过磁盘空间作为补充。这就像是你用信用卡,虽然方便,但用多了还是要还的。
- 内存分配:Linux内核使用不同的数据结构来分配内存,比如slab分配器和伙伴系统,这些都是为了高效地管理内存分配和回收。
- 内存映射:内存映射允许文件或设备直接映射到内存地址空间,这样可以提高I/O操作的效率。
- 页表:Linux使用页表来跟踪虚拟地址和物理地址之间的映射关系。这就像是你的通讯录,记录了每个人的电话号码。
- 交换空间(Swap) :当物理内存不足时,Linux会将一些不常用的内存页移动到磁盘上的交换空间。这就像是你把不常用的物品放到储物柜里。
- 内存回收:Linux内核会监控内存使用情况,并在需要时回收内存,比如杀死占用内存过多的进程。
Linux有几级页表
x86_64架构的四级页表结构如下:
- 页全局目录(Page Global Directory, PGD) :这是第一级页表,包含对下一级页表的引用。
- 页上级目录(Page Upper Directory, PUD) :在某些体系结构上,这可能是第二级或第三级页表,但在x86_64上,它通常是第二级。
- 页中间目录(Page Middle Directory, PMD) :这是第三级页表,在某些配置中,这一级可能不存在,页上级目录直接指向页表。
- 页表(Page Table) :这是第四级页表,包含对物理页帧的引用。
常用的设计模式
可分为创建型模式,结构型模式,行为型模式等
介绍一下工厂模式,以及为什么需要使用工厂模式
它的主要作用是定义一个创建对象的接口,让子类决定实例化哪一个类。这样,你就可以让系统的扩展不修改已有的代码,符合开闭原则(对扩展开放,对修改封闭)。
C++中class类型和struct类型的区别是什么
在C++中,class和struct本质上是相同的,都是用来定义自定义数据类型。但习惯上,我们用class来表示较大的、更复杂的数据结构,通常包含私有成员和公有成员函数,实现封装和数据隐藏。而struct则更倾向于简单的数据结构,成员默认是公共的(public),适合用来创建简单的数据记录。简而言之,class更适合实现面向对象编程,struct则更像C语言中的结构体。
哈希插入和删除的平均复杂度是多少
O(1)