• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
24
博客园    首页    新随笔    联系   管理    订阅  订阅

面试

C/C++:

 

1.指针和引用的区别

指针:指针就是内存地址,指针变量是用来存放内存地址的变量.不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。

引用:引用不是新定义一个变量,而是给已存在变量取一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间.

区别: 

  • 初始化:引用在定义时必须初始化,指针则没有要求(尽量初始化,防止野指针)
  • 引用在初始化引用一个实体后,就不能再引用其它实体,而指针可以在任意时候指向一个同类型实体
  • 没有NULL引用,但是有nullptr指针
  • 在sizeof中含义不同: 引用结果为引用类型的大小,但指针始终是地址空间,所占字节个数(32位平台占4个字节)
  • 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  • 有多级指针,但没有多级引用
  • 访问实体的方式不同,指针需要显式解引用,引用编译器自己处理
  • 引用比指针使用起来相对安全

2.C++的特性

封装:将数据和行为(或功能)有机结合起来,形成一个整体。把数据和处理数据的操作结合形成类,数据和函数都是类的成员。增强安全性和简化编程。对外隐藏实现细节暴露公共接口。外部通过接口来调用。

特点:提高复用性,提高安全性

 

继承:继承就是A类被B类继承,A类为父类,B类为子类。B类继承Al类的所有公共和保护成员数据(属性)和成员函数(方法)。子类可以重新定义父类某些属性,重写父类的某些方法,即覆盖父类的某些属性和方法。使其获得与父类不同的功能。

特点:

  1. 减少重复代码,增加复用性。
  2. 让类与类之间产生关系,是多态的前提。
  3. 增加了类与类之间的耦合性

 

多态:一个接口多种实现状态。多态的出现大大提高了程序的扩展性。

静态多态:

  1. 在同一个作用域对函数进行重载(函数名相同,函数参数列表不同)。
  2. 对函数进行模板化,忽略数据类型强调数据操作

动态多态:

  1. 基于封装和继承的来实现的,多个子类对继承于一个父类的虚函数进行重写,来实现不同状态。

多态的体现:

  1. 父类引用或指针指向子类对象。
  2. 父类的引用或指针可以接受子类对象。

多态的前提:

  1. 必须存在父类与子类的继承关系。
  2. 父类中必须有虚函数。
  3. 子类必须重写父类的虚函数。
  4. 父类引用或指针指向子类对象。

 

3.堆和栈的区别

一个由C/C++编译的程序占用的内存分为以下几个部分 :
  1、栈区(stack)—   由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 
  2、堆区(heap) —   一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。 
  3、全局区(静态区)(static)—  全局变量和静态变量的存储是放在一块的,初始化的 全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统放。 
  4、文字常量区   —  常量字符串就是放在这里的。 程序结束后由系统释放 
  5、程序代码区  —  存放函数体的二进制代码。 

 

申请方式:

stack:   由系统自动分配。 例如,声明在函数中一个局部变量   int   b;   系统自动在栈中为b开辟空间

heap:   需要程序员自己申请,并指明大小,在c中malloc函数   如p1   =   (char   *)malloc(10);   在C++中用new运算符   如p2   =   new   char[10];   但是注意p1、p2本身是在栈中的。   

 

申请后系统的响应:

栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

   
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程 序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

 

申请大小的限制:

栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。   


堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

 

申请效率的比较:

栈  由系统自动分配,速度较快。但程序员是无法控制的。   


堆  是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.   另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一块内存,虽然用起来最不方便。但是速度快,也最灵活。

 

堆和栈中的存储内容:

栈: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。  当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。   


堆: 一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。  

 

 

4.静态编译和动态编译

  动态编译的可执行文件需要附带一个的 动态链接库,在执行时,需要调用其对应动态链接库中的命令。所以其优点一方面是缩小了执行文件本身的体积,另一方面是加快了编译速度,节省了 系统资源。缺点一是哪怕是很简单的程序,只用到了链接库中的一两条命令,也需要附带一个相对庞大的链接库;二是如果其他计算机上没有安装对应的 运行库,则用动态编译的可执行文件就不能运行。


  静态编译就是 编译器在编译可执行文件的时候,将可执行文件需要调用的对应动态链接库(.so)中的部分提取出来,链接到可执行文件中去,使可执行文件在运行的时候不依赖于动态链接库。所以其优缺点与 动态编译的可执行文件正好互补。

 

6.析构函数 虚析构 纯虚析构函数的区别和作用

多态使用时,如果子类中有属性开辟到 堆区,那么父类指针在释放时无法调用到子类的析构代码

解决方式:将父类中的析构函数改为 虚析构 或者 纯虚析构

虚析构和纯虚析构共性:

  • 可以解决父类指针释放子类对象

  • 都需要有具体的函数实现

虚析构和纯虚析构区别:

  • 如果是纯虚析构,该类属于抽象类,无法实例化对象

 

 

操作系统:

 

1.进程和线程的区别

  • 进程是资源分配单位,线程是CPU调度单位;
  • 进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如寄存器和栈;
  • 线程同样具有就绪、阻塞和执行三种基本状态,同样具有状态之间的转换关系;
  • 线程能减少并发执行的时间和空间开销:
    • 线程的创建时间比进程短;
    • 线程的终止时间比进程短;
    • 同一进程内的线程切换时间比进程短;
    • 由于同一进程的各线程间共享内存和文件资源,可直接进行不通 过内核的通信;

 

2.线程池如何实现

通过管理一个任务队列、线程队列,将主线程中用户提交任务到一任务队列中,空闲的线程将从任务队列中获取任务并执行,用户可以异步的获取提交任务的执行结果。

基本框架如下图所示。这里的任务调度执行策略为:任务队列无上限,同时执行任务的数量固定,有空闲线程时获取队列中的队头任务。

线程池的线程是复用的,线程池中的线程创建后不销毁,直到线程池关闭退出。每个线程创建后,循环执行从任务队列获取任务并执行。

线程池与任务队列之间需要匹配,是一个典型的消费者-生产者模型,需要解决资源访问冲突,并且保证任务为空时,线程应该等待(阻塞),即需要实现线程安全、有同步机制的任务队列。

 

 

3.线程池的同步机制

 

4.select、poll 和 epoll的区别

9.2 I/O 多路复用:select/poll/epoll | 小林coding (xiaolincoding.com)

 

5.什么时候会进行内核态和用户态的转换

用户空间:指的就是用户可以操作和访问的空间,这个空间通常存放我们用户自己写的数据等。

内核空间:是系统内核来操作的一块空间,这块空间里面存放系统内核的函数、接口等。

在用户空间下执行,我们把此时运行得程序的这种状态成为用户态,而当这段程序执行在内核的空间执行时,这种状态称为内核态。

用户态切换到内核态的3种方式:

a.系统调用

这是用户进程主动要求切换到内核态的一种方式,用户进程通过系统调用申请操作系统提供的服务程序完成工作。

b.异常
当CPU在执行运行在用户态的程序时,发现了某些事件不可知的异常,这是会触发由当前运行进程切换到处理此
异常的内核相关程序中,也就到了内核态,比如缺页异常(硬中断)。

c.外围设备的中断
当外围设备完成用户请求的操作之后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条将要执行的指令
转而去执行中断信号的处理程序,如果先执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了有
用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。

 

6.定时器的实现原理

 

 

 

 

计算机网络:

 

1.tcp三次握手四次挥手

 

2.三次握手为什么不能是两次

 

3.四次挥手最后一次丢失了会怎样

 

4.udp如何实现可靠数据传输

 

5.http的字段

 

 

 

数据库:

 

1.索引的结构

 

2....

 

 

 

代码:

 

给一个序列,求出所有子串

 

posted @ 2023-03-24 21:05  wxk1213  阅读(42)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3