C++ 面试
1. TCP和UDP的区别
- TCP是面向连接的可靠传输;而UDP是面向无连接的不可靠传输;
- TCP确保所传输的数据一定会到达目的地,但时间却不能保证;而UDP不确保数据会按照原来的顺序到达,但具有实时性;
- TCP的使用场景是不怎么在意传输速度,但在意数据的准确性;而UDP的使用场景则是对实时性要求较高;
- TCP的首部开销大,占用20字节;而UDP的首部开销小,只占用8字节;
- TCP只支持点对点的数据传输;而UDP支持一对一、一对多、多对多等各种场景
- TCP需要校验和、序列号、超时重传、确认机制、连接管理(三次握手和四次挥手)、流量控制和拥塞控制来确保传输的可靠性,当网络拥塞时,速度会比较慢;UDP没有拥塞控制和流量控制这些。
2. new和malloc的区别
- new/delete 是C++的操作符,malloc/free 是C中的函数;
- new 产生的是一个对象,而malloc 分配的是一块内存;new 产生的对象可以用成员函数访问,而malloc分配的是一块内存区域,用指针访问,可以在里面移动指针;malloc申请的空间不能初始化,new可以初始化;
- malloc 申请空间时,需要手动计算空间大小并传递;new 只需在其后跟空间的类型,然后是多个对象,就只需要new类型的数组;
- malloc 返回值类型为void*,在使用时必须强转,new不需要,因为new 后面跟的是空间的类型;
- malloc 申请空间失败时,返回的是NULL,因此使用时必须判空;而new 不需要,但是new 需要捕获异常。
3. delete和free的区别
- delete是操作符,而free是函数;
- delete用于释放 new 分配的空间,free 用于释放 malloc 分配的空间;
- delete会调用析构函数(析构函数中会把指针修改为NULL),而 free 不会;
- 使用 delete 释放内存则不需要检查指针是否为NULL;而调用 free 之前需要检查需要释放的指针是否为空。
4. struct和class的区别
- 在C++中两者的唯一区别就是默认的访问权限不同。
- struct默认权限为共有。
- class默认权限为私有。
拓展: 在C中,struct是用户自定义数据类型,是一些变量的集合体。没有权限设置,不能包含函数;在C++中,struct是抽象数据类型,能给用户提供接口,能定义成员函数,能继承也能实现多态,有权限设置。
5. struct和union的区别
- 在存储多个成员信息时,struct占用的空间由每个成员的大小加起来;union占用的空间取决于它所有的成员中,占用空间最大的一个成员的大小,并且它的大小要能被其他的成员的大小整除;
- 在使用时,struct中所有成员都有占用空间,所以都可以使用;而union中在一个时刻只能使用一个成员;
6. 多态是怎么实现的
多态分为静态多态(编译时多态)和动态多态(运行时多态)。
- 静态多态通过重载来实现的。重载是在一个类里面,方法名字相同,而参数不同。返回类型可相同也可不同,每个重载的方法(或构造函数)都必须有一个独一无二的参数类型列表。
- 动态多态通过继承、重写、向上转型实现的。使得父类指针或引用在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而执行不同的行为(调用虚函数)。也就是在运行时会根据对象的实际类型来调用相应的函数。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中虚函数进行重写(重写就是子类父类都有这个虚函数,且子类的虚函数与父类虚函数的函数名、参数和返回值都相同,但需要注意的是,参数只看类型是否相同,不看缺省值,相对于只重写了父类虚函数中的实现部分,就是如果子类父类参数中有缺省值,当用多态时,会使用父类的缺省值),重写后,在调用这些虚函数时就会调用子类的虚函数。
向上转型:在多态中需要将子类的指针或引用赋给父类对象,只有这样该指针或引用才既能调用父类的方法,又能调用子类的方法。
一篇把多态讲得很全面的博文分享给大家
7. 指针和引用的区别
- 定义和性质不同。指针是一种数据类型,用于保存地址类型的数据,而引用可以看成是变量的别名;
- 指针变量可以为空,在任何时候初始化,而引用不可以为空,当被创建时就必须初始化;
- 指针可以有多级,但引用只能是一级;
- 引用使用时无需解引用(*),指针需要解引用;
- 指针的值在初始化后可以改变,即指向其他的存储单元,而引用在进行初始化后就不会再改变了;
- 当调用sizeof时,指针的得到的时指针变量本身的大小,而引用得到的是所指向的变量(对象)的大小;
- 指针作为函数参数传递时传递的是指针变量(地址)的值(值传递),而引用作为函数参数传递时传递的时实参本身,而不是拷贝副本;
- 指针和引用进行++运算意义不一样。
8. C和C++的区别
- C是面向过程,而C++是面向对象;
- C++完全兼容C的内容;
- C++支持运算符重载、函数重载等编译时多态机制;
- C++支持泛型编程、模板机制;
- C++支持异常处理;
9. 动态库和静态库
静态库和动态库都是编程中常用的库文件,它们都包含了一些函数和数据,可以供程序调用。它们的主要区别在于编译时和运行时的不同。
静态库(Static Library 是在编译时将库文件的代码和数据复制到可执行文件中,程序运行时不再需要该库文件。静态库的优点是使用简单,不需要额外的安装和配置,而且可以保证程序的稳定性和可靠性。缺点是占用的空间较大,当多个程序使用同一个静态库时,会导致重复的代码和数据,浪费系统资源。
动态库(Dynamic Library) 是在程序运行时才加载的库文件,程序启动时只需要加载动态库的链接信息,而不需要将整个库文件复制到内存中。动态库的优点是占用的空间较小,多个程序可以共享同一个动态库,从而节省系统资源。缺点是使用较为复杂,需要安装和配置动态库,同时也可能会产生一些运行时的问题,如版本不兼容、依赖关系等。
在使用静态库和动态库时,需要注意以下几点:
-
静态库可以直接链接到可执行文件中,使用时需要将库文件的路径添加到编译器的链接选项中。动态库需要在运行时加载,使用时需要将库文件的路径添加到系统的动态库搜索路径中。
-
静态库会将库文件的代码和数据复制到可执行文件中,因此可执行文件的大小会增加。动态库不会将库文件的代码和数据复制到可执行文件中,因此可执行文件的大小不会增加。
-
静态库可以保证程序的稳定性和可靠性,因为库文件的代码和数据已经被复制到可执行文件中。动态库可能会有版本不兼容、依赖关系等问题,需要进行额外的配置和管理。
总之,静态库和动态库都有各自的优点和缺点,需要根据具体的需求和情况来选择使用哪种库文件。
10.简述 DNS 查询服务器的基本流程是什么?(深信服)
DNS负责域名和IP的转换。
DNS查询方式有两种,一种是递归查询(本地去查根,根没有会一直查询域服务器、解析服务器),另一种是迭代查询(本地去查根,根没有会告诉本地该去那里查,要是还没有又是本地去另外的服务器查,反正就是本地自己去查),下面介绍的就是迭代查询。
- 打开浏览器,输入一个域名。比如输入www.baidu.com,这时,你使用的电脑会发出一个DNS请求到本地DNS服务器。 本地DNS服务器一般就是你的网络接入服务商提供,如中国移动、中国电信;
- DNS请求到达本地DNS服务器之后,本地DNS服务器会首先查询它的缓存记录,如果缓存中有此条记录,就可以直接返回结果。如果没有,本地DNS服务器还要向DNS根服务器进行查询;
- 根DNS服务器没有记录具体的域名和IP地址的对应关系,而是给出域服务器的地址,告诉本地DNS服务器,你可以到域服务器上去继续查询;
- 本地DNS服务器继续向域服务器发出请求,在这个例子中,请求的对象是.com域服务器。.com域服务器收到请求之后,也不会直接返回域名和IP地址的对应关系,而是告诉本地DNS服务器,你的域名的解析服务器的地址;
- 最后,本地DNS服务器向域名的解析服务器发出请求,这时就能收到一个域名和IP地址对应关系,本地DNS服务器不仅要把IP地址返回给用户电脑,还要把这个对应关系保存在缓存中,以备下次别的用户查询时,可以直接返回结果,加速网络访问。
11. 什么是泛型编程
泛型编程(Generic Programming)是一种编程方法论,它的目的是编写可重用、通用的代码,以实现更高效、更灵活的软件开发。泛型编程的核心思想是将算法和数据结构的实现与其所操作的数据类型分离开来,从而实现代码的通用性和可重用性。
在 C++ 中,泛型编程的实现依赖于模板(Template)机制。模板是一种可以在编译时生成代码的机制,它允许我们编写通用的代码,可以适用于多种不同的数据类型。通过使用模板,我们可以将算法和数据结构的实现与具体的数据类型分离开来,从而实现代码的通用性和可重用性。
C++ 标准库中的许多容器、算法和函数都是使用泛型编程实现的。例如,std::vector、std::list、std::set 等容器都是使用模板实现的,可以适用于不同的数据类型。同样,std::sort、std::find、std::transform 等算法也是使用模板实现的,可以适用于不同的数据类型。
12. UDP怎么模拟TCP传输
UDP是一种不可靠的传输协议,而TCP是一种可靠的传输协议。UDP不保证数据传输的可靠性和完整性,因此不能像TCP那样保证数据的准确性和可靠性。但是,可以通过一些技术手段来模拟TCP传输,以保证数据传输的可靠性和完整性。
以下是一些常见的技术手段:
-
应用层协议:可以使用一些应用层协议来保证数据的可靠传输,如HTTP、FTP等。这些协议在传输数据时会对数据进行一些处理,以保证数据的完整性和可靠性。
-
UDP包的确认和重传:可以通过在应用层实现UDP包的确认和重传机制,来模拟TCP传输。UDP包的确认和重传机制可以保证数据的可靠传输。
-
超时重传:当发送方发送数据包时,可以设置一个超时时间,如果在该时间内没有收到接收方的确认包,则认为数据包丢失,需要重新发送。
-
拥塞控制:可以使用拥塞控制算法来限制发送方的发送速率,以避免网络拥塞,从而保证数据的可靠传输。
总之,虽然UDP不是一个可靠的传输协议,但是可以通过一些技术手段来模拟TCP传输,以保证数据的可靠性和完整性。