参赛话题:面试宝典
距离上一次的前端面试宝典的发布已经有一段时间了,在这一段时间,也有很多文章和大家共同分享了其他方面的技术,当然也在学习的过程中遇到过很多难题,现在就把在学习中遇到过的一些在面试中也会提到的问题分享给大家,期待和小伙伴们的交流呀~
面试流程
大二计算机小白一枚,很多详细的面试流程还不了解,但是已经在入手面试题目了,刚开始很基础的面试题目也能把我整的云里雾里的,根本无从下手,才知道自己的水平是多么的不好,不过每一次的程序bug都能给我不小的收获,在网上查了查大部分公司的面试流程,并把一些已经在计算机岗位上实习的学长学姐给出的一些意见做了做汇总,大致上是了解了,但是万变不离其宗,无论怎样的面试,岗位相关的专业知识肯定是会问的,这篇文章总结了两个计算机岗位面试经常问道的题目,持续学习积累中,这篇文章涉及到的知识一定不仅限于此。
面试题
面试题一:
对于堆和栈你是如何理解的,最好是用一个简单的程序描述一下。
问题剖析:
堆和栈的问题可以说是在计算机的学习中很常见的了,特别是在数据结构中,“堆”,“栈”绝对是经常出现的字眼,首先我们来简单回顾一下堆和栈是什么,然后可以从两者的区别联系方面来回答这个问题,并利用一个简单的c++程序来描述一下:
堆,是动态分配内存的一种存储形式,随意读取且方便。
可以看成一组数组对象以二叉树的形态分布,运行时动态分配内存,对读取顺序无限制。
栈,是一种只能后进先出读取的线性表,读取顺序限制性强。
是一种仅在表尾进行插入和删除操作的线性表,遵循后进先出的原则。
问题解答:
堆和栈的区别与联系
堆 是一种动态的概念,它的大小是受动态变化的,取决于程序运行的那一刻所计算的数据,其访问速度相对于栈来说比较慢;堆是在进程中进行的,并且不是独立进程,因此所有的线程都可以对堆进行访问,从访问权限上来说是线程不安全的。
栈 是一种静态概念,它的大小是在编译时由程序员确定好的;比如函数的调用就是在栈上进行的,当一个函数被调用后,里面的权限是无法被另一个栈访问的,也就是说不同函数之间的栈数据是无法共享的,那么在安全性上就要比堆安全;
优缺点
说到这里,堆和栈的优缺点应该也能答出来一二了吧:
堆
优点:堆申请的空间大;可以动态地分配内存大小。
缺点:内存泄漏。如果由于某种原因程序没有释放,就会造成内存泄漏,出现内存浪费;比如在c++中,我们使用new来创建一个对象时,返回的是一个对象指针,这个指针指向本类刚创建的这个对象。在c++中分配给指针的只有存储指针值的空间,但对象所占用的空间分配在堆上,因此使用new来创建对象时,必须使用delete来释放内存。
易产生内存碎片。前面说到了堆的处理效率是比较低的,因此就会产生很多自定义的内存碎片;
线程不安全。因为堆不是独立进程,在程序运行过程中其他的进程可以对其进访问。
栈
优点:线程独立,安全性较高;栈数据是可以共享;内存可以及时得到回收,内存更好管理。
缺点:栈获得的空间较小,存在栈中的数据大小和生存期必须是确定的,数据的固定性也让栈缺乏灵活性。
栈溢出问题(stack overflow)由于栈的大小是有限的,当出现局部数组过大或递归调用层次过多,会超出栈的容量;并且栈上的buffer是大小固定的,如果指针或者是数组越界的话,就会影响到栈上原有的数据,造成栈溢出问题。
程序描述
这里用到了c++中的析构函数来简单解释一下堆和栈(当然在实际开发当中堆和栈远比这要复杂的多,举个简单的小例子比较容易懂):
using namespace std; class A { public: A() { cout<<"A的构造函数" <<endl; } ~A() { cout<<"A的析构函数"<<endl; } }; class B { A *a;//在B中定义一个指针 public: B() { cout<<"B的构造函数"<<endl; a=new A;//指针指向堆区空间 ,使用new生成对象指针时,自动调用本类的构造函数 } ~B() { cout<<"B的析构函数" <<endl; delete a;//使用关键字new 创建的对象,用delete来撤销 ;使用delete删除这个对象时,首先调用本类的析构函数,再释放占用的内存。 } }; int main() { B b;//B的对象b定义在栈区,出栈之后自动调用本类的析构函数 return 0; }
假如将“delete a;”注释掉,那么就会出现内存泄露的情况,而析构函数可以清理类中有指针、并且指向堆区空间的成员,释放指针指向的堆区空间,防止内存泄露。
假如我们要使用内存庞大的数据或者是数据大小不确定的时候可以使用堆;如果数据内存较小的话,我们可以使用栈。
简单补充
在js的数据类型中,我们知道有基本数据类型和引用数据类型,其中
基本数据类型: Number、String、Boolean、Undefined、Null、Symbol(es6新增的原始数据类型)是存储在栈中的,基本数据类型大小固定,占据空间小,被频繁使用。它的赋值方式是深拷贝。
引用数据类型: object、 array、 function 存在堆中。当我们需要访问这三种引用类型的值时,首先得从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。它的数据类型是浅拷贝。
举个例子:
//基本数据类型(深拷贝,存放在栈) var a=10; var b=a; console.log(b);//输出10
// 引用数据类型(浅拷贝,存放在堆) var a=Object();//a的数据类型是object var b=a; b.num="20";//b的num属性添加到堆内存中,实际上a和b共同指向了一个堆内存对象 console.log(a.num);//输出20
面试题二:
进程和线程的区别联系(计算机的经典八股之一)
问题剖析:
这个问题算是比较常问的了,但是想要说出比较标准的答案,还是要理解加记忆的(觉得简单的可以不用看了哈)。
问题解答:
进程:
(抽象的定义)进程是具有独立功能的程序在某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位。
从操作系统的角度来看,可以将进程分为系统进程 和用户进程,系统进程执行操作系统程序,完成操作系统的某些功能;用户进程运行用户程序,直接为用户服务。系统进程的优先级通常要高于一般用户进程的优先级。
进程是程序的一个执行过程,是动态的,并且是由程序、数据、进程控制块三部分组成
两个基本属性:进程是一个可拥有资源的独立单位;进程是一个可以独立调度和分派的基本单位。
进程的状态转换:
线程
在操作系统中引入线程,可以减少程序并发执行时所花费的时间和空间开销,使得操作系统由更好的并发性。
进程与线程的区别和联系
联系:在引入了线程的操作系统中,通常一个进程有若干个线程,至少需要有一个线程,也就造成了进程中任意一线程执行出错,都会导致整个进程的崩溃;通常在操作系统中,拥有资源的基本单位和独立调度、分派的基本单位都是进程,当在引入线程的操作系统中,会把线程作为调度和分配的基本单位,并把进程作为资源拥有的基本单位。
区别:
进程是资源分配的最小单位;线程是CPU调度的最小单位,也是程序执行的最小单位。
从调度的角度来看,进程之间的切换所需开销要不线程的多;线程的切换也不会引起进程的切换,但是如果是某个进程中的线程切换到另一个进程中的线程就会引起进程的切换;
在系统开销方面,在进行进程切换时,会涉及到当前执行进程CPU环境以及各种状态的保存和新调度进程的设置;但在线程切换时只需要保存和设置少量的寄存器内存,开销比较小;
在通信方面,进程之间的内容是相互隔离的,如果想要实现进程之间的通信,就需要使用进程间的通信机制了;而多个线程可以共享同一个进程的资源的。
补充
了解了进程和线程之间的区别与联系,我们可以简单总结一下什么时候用进程,什么时候用线程:
我们可以把进程当作一个大公司,而线程就是这个大公司里运行的各个部门,大公司当然是用来拿下一整个项目的啦,而各个部门就是各自做各自的工作,来共同完成这个大项目:
1:从花销方面来讲,创建一个进程开销要大,那么当我们频繁的创建或销毁时,可以使用线程;
2:需要进行并行操作时需要线程(就像公司里的各个部门负责各自的工作一样);
3:当需要传输大量的数据时可以采用线程,因为线程之间不仅切换速度较快,而且开销也小;
4:当需要安全稳定的传输一些数据时,需要采用进程;
在B站发现一个对进程和线程讲解比较详细的视频,感兴趣的伙伴可以看一下 点击查看
个人经验总结
以上就是计算机小白总结的面试tips啦,我相信在今后的学习中,这篇文章肯定会不断补充和完完善的,毕竟学无之境!虽然还没有遇到过面试,但是早点准备让我收获很多,也让自己沉淀了不少,还是那句话,无论子啊面试哪个岗位,沉着应对,随机应变都是至关重要的;面试前的准备也是必不可少的,毕竟只有充分的准备,我们才有更多冷静下来认真回答问题的机会,所以加油吧,相信你一定可以早日走到自己心仪的岗位!
资料总结/刷题指南
在面试前的准备可以从刷题总结入手,首次可以尝试牛客、洛谷;再然后就是力扣刷题,经典的算法题目经得起反复刷和理解,遇到某个不易理解的知识点可以在网上找视频和网站学习,一瞬的沉着断然离不开长期的积累与学习,加油!
持续学习和积累更新中,愿和大家一起交流,计算机小白一枚,如有不足之处,感谢指点!