【秋招面试题】C++ 网络编程 面试题库(一) 一、线程池的设计及作用 线程池的作用: 线程池是为了解决线程在程序中因频繁创建和销毁而消耗大量时间而存在的,即在程序开始正式任务之前,先创建出一些线程,这些线程在程序不会被销毁,而且程序在运行中也不会再去创建线程。这样在程序的运行期间就提高了效率。 线程池的设计思路: 先创建出一组线程,当有新任务进来时就从线程池中取出空闲线程处理任务,任务完成之后又重新放回去,当线程池中的所有线程都在任务时,只能等待有线程结束任务才能继续执行。 二、线程和进程的区别 根本区别:进程是操作系统资源分配的基本单位,而线程是CPU任务调度和执行的基本单位 在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。 所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行) 内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。 包含关系:一个线程只能属于一个进程,但是一个进程可以拥有多个线程。多线程处理就是允许一个进程中在同一时刻执行多个任务。所以线程也被称为轻权进程或者轻量级进程。 三、C++ 设计模式 单例模式 概念:是指在内存中只会创建且仅创建一次对象的设计模式 优点: 1.保证一个类只有一个实例,并提供一个访问它的全局访问点,使得系统中只有唯一的一个对象实例。这样就 防止其它对象对自己的实例化,确保所有的对象都访问一个实例 2.由于在系统内存中只存在一个对象,因此可以节约系统资源、提高系统的性能。 缺点: 就是不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。 实现要点: 在类中,要构造一个实例,就必须调用类的构造函数,并且为了保证全局只有一个实例, 需防止在外部调用类的构造函数而构造实例,需要将构造函数的访问权限标记为private, 同时阻止拷贝创建对象时赋值拷贝对象,因此也将它们声明并权限标记为private; 另外,需要提供一个全局访问点,就需要在类中定义一个static函数,返回在类内部唯一构造的实例。 观察者模式 观察者模式定义了对象间的一对多依赖关系,让一个或多个观察者对象观察一个主题对象。当主题对象的状态发生变化时,系统能通知所有的依赖于此对象的观察者对象,从而使得观察者对象能够自动更新。 实现方式: a) 角色抽象类(提供对观察者的添加,删除和通知功能)。 b) 角色具体类,实现a,维护一个c的集合(对角色抽象类的实现)。 c) 观察者抽象类(被角色通知后实现的方法)。 d) 观察者实现类,实现c(多个)。 工厂模式 工厂模式包括三种:简单工厂模式、工厂方法模式、抽象工厂模式。 工厂模式的主要作用是封装对象的创建,分离对象的创建和操作过程,用于批量管理对象的创建过程,便于程序的维护和扩展。 简单工厂是工厂模式最简单的一种实现,对于不同产品的创建定义一个工厂类,将产品的类型作为参数传入到工厂的创建函数,根据类型分支选择不同的产品构造函数。 四、进程间的通讯方式 管道:数据只能单向流动,速度慢,容量有限,只有父子进程能通讯 消息队列:就是一个消息的链表,是一系列保存在内核中消息的列表。用户进程可以向消息队列添加消息,也可以向消息队列读取消息。 共享内存:映射一段能被其他进程访问的内存,这段内存由一个进程创建,但多个进程都可以访问; 信号量:是一个计数器,用于控制多个进程间对共享资源的访问; 套接字:用于不同计算机之间的不同进程间通信。 五、引用和指针的区别 本质:引用是别名,指针是地址 相同点:都是地址的概念; 指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。 不同点: 1.引用不可以为空,但指针可以为空 ,故定义一个引用的时候,必须初始化 2.引用不可以改变指向,对一个对象”至死不渝”;但是指针可以改变指向,而指向其它对象,虽然引用不可以改变指向,但是可以改变初始化对象的内容 3.引用的大小是所指向的变量的大小,因为引用只是一个别名而已;指针是指针本身的大小,4个字节 4.引用比指针更安全。由于不存在空引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,因此引用很安全。对于指针来说,它可以随时指向别的对象,并且可以不被初始化,或为NULL,所以不安全。 5.引用仅在声明时带有引用运算符“&”,以后像普通变量一样使用,不能再带“&”,其它场合使用的“&”都是地址操作符。 六、构造函数和析构函数 构造函数的作用:用于新建对象的初始化工作。(一个类可以有多个构造函数,构造函数可以重载,不可以加虚函数) 析构函数的作用:用于在撤销对象前,完成一些清理工作,比如:释放内存等。(一个类只能有一个析构函数,不可以重载) 拷贝构造函数:拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量,该参数是const类型,不可变的。 七、深拷贝和浅拷贝 浅拷贝:浅拷贝是对指针进行拷贝,拷贝后两个指针指向同一块内存空间。C++中如果不定义类的赋值构造函数,就会调用类的默认赋值构造函数,而类的赋值构造函数是浅拷贝。 深拷贝:深拷贝是对指针进行拷贝而且还对内容进行拷贝,拷贝完成后,指针指向的地址不一样,但是值是一样的。 浅拷贝和深拷贝的区别:前者就是使用编译器提供的默认拷贝构造函数或者默认赋值构造函数。后者是自己显示实现的拷贝/赋值构造函数。 八、对多态的理解 C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类类,别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。 多态的实现主要分为静态多态和动态多态,静态多态主要是重载,在编译的时候就已经确定;动态多态是用虚函数机制实现的,在运行期间动态绑定。 多态的条件: 1.必须有继承 2.要有虚函数重写 3.用父类指针(引用)指向子类对象 多态的基础理论: 联编:一个程序模块,代码之间互相关联的过程 动态联编:把程序联编的过程,推迟到运行时进行 静态联编 多态的实现效果: 同样的调用语句,不同的表现形态 多态的意义:设计模式的基础、编写框架的基础、函数指针做函数参数 九、数据结构有哪些 什么是数据结构: 数据结构是指相互之间存在着一种或多种关系的数据素的集合和该集合中数据素之间的关系组成 。 常用的数据结构有:数组,栈,链表,队列,树,图,堆,散列表等。 数组:数组是可以在内存中连续存储多个素的结构,在内存中的分配也是连续的,数组中的素通过数组下标进行访问 栈:栈是一种特殊的线性表,仅能在线性表的一端操作,栈顶允许操作,栈底不允许操作。 栈的特点是:先进后出,或者说是后进先出。 队列:队列与栈一样,也是一种线性表,不同的是,队列可以在一端添加素,在另一端取出素,也就是:先进先出。 链表:链表是物理存储单上非连续的、非顺序的存储结构,数据素的逻辑顺序是通过链表的指针地址实现,每个素包含两个结点,一个是存储素的数据域 (内存空间),另一个是指向下一个结点地址的指针域。根据指针的指向,链表能形成不同的结构,例如单链表,双向链表,循环链表等。 树:树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。 十、socket包安全 TCP是一个基于字节流的传输服务,”流”意味着TCP所传输的数据是没有边界的。这不同于UDP提供基于消息的传输服务,其传输的数据是有边界的。TCP的发送方无法保证对等方每次接收到的是一个完整的数据包。就会出现分包或粘包的问题. 分包:传输数据不完整,一条信息被分成多次发送。 比如我们发送了一条信息:“你好”,我们可能只收到了“你”,却没有收到“好”,这样就会导致数据的不完整。 粘包:传输的多条数据粘在一起,比如我发了“你好”和“我是小胖”,我们可能会收到“你好我是小胖”,也可能收到“你好我是”“你好我”“你好我是小”,后几种情况是分包粘包同时发生,我们肯定不期望这种现象发生,所以我们就有必要对我们发送的数据进行编辑。 Socket只是一种通信手段它本身没有任何额外的安全措施,所以要用到加密技术 ,不然通信的数据非常容易初攻击者到,一般情况下,我们会使用CRC进行冗余验证,看数据包是否传输完整,然后自定义自己的加密方式,将数据包加密以后再发出,有的项目还会对数据包进行压缩,所以我们这里给出一种通用的结构:数据头(长度)+冗余验证(CRC)+是否压缩+包体(加密后)。 十一、new和malloc的区别

2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/79240.html
