C++面试题

本文详细解析了进程与线程的概念及其区别,包括资源分配、调度运行、进程间通信方式等内容。同时,对比了插入排序、冒泡排序、选择排序、归并排序和快速排序等算法的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 进程与线程的区别和联系?

答:进程:进程是表示资源分配的基本单位,又是调度运行的基本单位。例如,用户启动了一个程序,系统就为其创建一个进程,又为其分配资源(表格,内存,IO等),然后将其放入进程的就绪队列中,进程调度程序选中它后,才为它分配CPU及其他相关资源,该进程才真正开始,所以,进程是系统中并发执行的单位。

线程:进程中执行运算的最小单位,即执行处理机调度的基本单位。

线程是进程的一个实体,是CPU调度和分配的基本单位,它是进程更小的能独立运行的基本单位,线程基本上不拥有资源,只拥有一些在运行中必不可少的资源。

进程间通信:管道,共享内存,socket,信号,消息队列

       2.各种排序算法的比较?插入排序,冒泡排序,选择排序,归并排序,快速排序的写法。

答:常用的几种排序算法的时间复杂度,冒泡排序O(n^2),插入排序O(n^2),选择排序O(n^2),快速排序最理想的算法时间复杂度为O(nlog2n),最坏的情况O(n^2).堆排序(nlogn),归并排序的时间复杂度为O(nlog2n)

  1. 标准模板库的使用?vector,map,string,set,list等的使用?

答:STL是一个具有工业强度的、高效的C++程序库它是最新的C++标准函数库中的一个子集,包含容器、算法、迭代器。

Vector和数组类似,他拥有一段连续的内存空间,并且起始地址不变,因此它可以很好地支持随机存取,(使用[]操作符来访问其中的元素),由于它的内存空间是连续的,所以在中间进行插入和删除会造成内存块的拷贝(时间复杂度为On),另外,当数组的内存空间不够时,需要重新分配是原来两倍的内存并且进行内存拷贝。

List是由数据结构的双向链表实现的,因此它的内存空间是不连续的,只能通过指针来进行数据的访问。它对随机存取变得没有效率,需要遍历中间的元素,搜素时间复杂度为O(n),由于链表的特点,它可以又很好地效率来支持任意地方的删除和插入。

Map和set的内部结构是一个平衡二叉树。 AVL-tree,RB-tree,AA-tree.STL的底层机制都是以RB-tree(红黑树)完成的,红黑树的平均和最坏情况下的插入、删除,查找时间复杂度为O(lgn).

  1. 哈希表的介绍?怎样解决哈希冲突?

答:哈希表又称为散列表,这种方法的基本思想是首先在元素的关键字k与元素的存取位置p之间建立一个对应关系F,即p=f(k);

F又称为哈希函数。   当关键字的集合很大时,关键字的不同元素有可能映射到哈希表的同一位置上,我们称之为哈希冲突。

哈希函数的构造:伪随机法,除留余数法,数据分析法,平方取中法,分段叠加法。    解决哈希冲突的方法:开放定址法,再哈希法和链地址法。

  1. 智能指针的介绍?

答:动态内存的分配,有可能发生异常导致内存溢出的风险。智能指针就是促使动态内存和异常之间进行平滑的交互,auto_ptr保证当异常抛出时,分配的对象能够自动销毁,内存能被自动释放。

智能指针的实现:

  1. 面向对象与面向过程的区别与联系?

答:C语言是一个结构化语言,它的重点在于数据结构与算法,通过一个过程,对输入进行运算处理得到输出。C++首先考虑的是如何通过构造一个对象模型,让这个模型能够解决对应的问题。

面向对象的特征:抽象、封装、继承和多态。

编译时多态是通过运算符重载和函数重载实现的,运行时多态是通过虚函数来实现的。

  1. 虚函数的实现机制?

答:虚函数是通过虚函数表的,事实上如果一个类中有虚函数,则系统会为这个类分配一个指针指向一张虚函数表,表中每一项指向一个虚函数地址,实际上就是一个函数指针的数组。

 把绑定所需要的信息记录用一种通用的数据结构记录下来,该数据结构可以同对象指针相联系,在编译时只需要这个数据类型进行抽象的绑定,而在运行期间才会真正的绑定。这个数据类型就是虚函数表。

如果一个类中有虚函数,那么它的大小最小为4,因为一个指针类型的大小为4.

  1. 链表的使用与介绍?

答:链表一种动态数据结构。是因为我们在创建链表的时候,无需知道链表的长度。插入和删除比较方便,随机读取比较方便。

  1. 深复制与浅复制的区别?

答:复制构造函数是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化。

浅拷贝是指新旧两个对象指向同一个外部的内容,而深拷贝是指为新对象制作了外部对象的独立复制。

  1. 复杂指针的声明

答:1.int (*func)(int* p)

*func是函数,而func是直向这类函数的指针,就是一个函数指针,这类函数有一个int*类型的形参,返回值类型为函数。

2.Int (*func)(int* p,int (*f)(int*));

(*func)是函数,而func是指向这类函数的指针,就是一个函数指针,该函数有两个参数第一个是int*类型,第二个是(*f)是一个函数,该函数有一个int*类型的参数,返回值为整型。

3.int (*func[5])(int *p)

Func数组的元素是函数类型的指针,该指针有一个int*类型的形参,并且返回值为整型

      4.int (*(*func)[5])(int* p)

Func是指针,括号外面有一个[]运算符,说明func是一个指向数组的指针,左边还有个*号,说明这个数组的元素的指针,右边有参数,说明func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int* 类型的的形参,返回值为int类型的函数。

      5.int (*(*func)(int *p))[5];

Func是一个函数指针,这类函数具有int*类型的形参,返回值值是指向数组的指针,所指向的数组的元素是具有五个int元素的数组。

  1. 七层网络模型?TCP的三次握手?

答:七层网络模型:物理层,数据链路层,网络层,传输层,会话层,表示层,应用层。

TCP的三次握手:https://i-blog.csdnimg.cn/blog_migrate/f374f336a108902d7fdf9f491a595f75.png

四次挥手:

https://i-blog.csdnimg.cn/blog_migrate/25b593d0e423f44032634cfdf9d0b1ad.png

  1. 什么是守护进程?什么是僵尸进程?

僵尸进程:在子进程未退出的情况下,父进程退出,子进程被init进程接管,但是子进程将不会正常退出,退出后也不会被收回该进程的资源,所以这种情况应该被避免,否则数量多了以后系统资源将被消耗完.为了避免这种情况可以是用vfork函数进行子进程的派生,或者在父进程中使用一下函数来等待子进程的退出:

守护进程:一直在后台运行,父进程为init,和僵尸进程类似,不同的是守护进程多为服务进程,是需要一直提供服务所以不能退出.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值