找工做知识点总结

  1. 自我介绍以及询问问题的基本准备;
  2. 复习项目,项目实现细节,项目背景等;
  3. 复习基本算法:排序(尤为是堆排序和快排的实现),常见动态规划(最长公共子序列,最长递增子序列,编辑距离,第k大的数,Leetcode相关题目,位操做优化等);二分搜索;

双指针,hash表。node

  1. C++语言基础:volatile, const, static, 内存泄漏,智能指针,malloc与new,指针与引用,类型转换,c++11的移动语义完美转发;C++内存布局(通常的内存布局,有虚函数的内存布局<如何实现>, 虚继承的布局);C++面向对象(封装多态抽象,构造函数<成员初始化列表>,复制构造函数<NRV优化>,赋值构造函数,重载函数,Inline函数,友元,动态联编,重载操做符,模板,设计String类),接口与抽象类。

Volatile: 对于一段代码中的变量,若是没有加volatile关键字申明,那么编译器将会进行优化,假定该变量首次和第二次出现之间,没有修改,直接预读取以前的值。而加入volatile,则告诉编译器不要进行这样的优化,避免出现寄存器修改,使得每次都从地址中去读取这个值。react

  1. Stl相关知识:迭代器实现与Traits技法;内存管理(一级与二级);各类容器的内部实现<vector, list, set, map>, hash_table<hash基础,冲突解决,拉链法>;
  2. 设计模式:单例模式,简单工厂,模板模式,解释器模式,迭代器模式,代理模式,策略模式,装饰模式,观察者模式,适配器模式。
  3. 数据库:索引实现,不一样索引比较;事务及事务例子;sql语句执行顺序,sql基本语句;不一样引擎对比(myisam,Innodb),优化
  4. 网络:tcp状态转换的图(2MSL时间,time_wait状态,close_wait状态,半关闭状态的出现缘由危害及其解决方案;三次握手四次挥手过程及其缘由),tcp数据可靠性保证(超时重传发生条件,拥塞处理机制<慢启动,拥塞避免,快速重传,快速恢复>,窗口滑动协议),tcp与udp区别,各层的协议类型;
  5. 网络编程:socket链接各过程以及各个函数<listen的队列,connect的非阻塞模式,关闭的两种方式>;socket的选项(oob,地址重用SO_RESUADDR,SO_LINGER优雅关闭),Io多路复用三种的区别于实现<select,poll,epoll>;epoll的et和Lt模式比较,同步异步,阻塞非阻塞,读写操做(read,write,readv,writev,sendfile)
  6. 多线程与多进程:线程的同步与互斥方法(互斥锁,自旋锁,条件变量,join,信号量,屏障,读写锁区别与使用场景);进程的通讯方式(管道,FIFO,信号,消息队列,共享内存<实现原理与进程中地址>,socket,Unix域套接字);协程(setjmp,longjmp),多进程与多线程区别。生产者消费者问题,哲学家问题以及读写问题。
  7. Linux: 进程相关(fork,vfork,wait,cow,进程建立fork,执行exec与退出exit的方法,进程状态图,僵尸进程,孤儿进程,init进程,守护进程<实现原理与方法>, 进程通讯,进程关系<组长进程,会话,控制终端>,动态库静态库,进程存储空间布局,进程调度算法),文件系统(inode---文件Io实现,硬连接,软链接,以及文件相关的linux命令及其实现),内存管理(malloc,slab,伙伴系统),信号基本知识,sendfile,fcntl;线程池实现。
  8. 网络模型:reactor,proactor;
  9. 操做系统:死锁《缘由,银行家算法》,磁盘调度算法(电梯扫描,最短寻道时间,先来先服务);缺页中断选取(FIFO,LRU,LFU)
  10. Linux命令:性能命令(top,free….),调试相关命令(gdb,strace,core dump,valgrind),makefile书写,gdb常见命令(断点,进入断点,跳过finish,多线程调试如何搞),磁盘命令(iostat,df,du),进程(ps) 网络(netstat) ---(sar, uptime, pmap, ipcs, watch)
  11. 额外:大小端;内存大小(union, struct, class)--字节对齐; c实现封装,继承等如何作。函数调用过程,中断与系统调用,堆栈
  12. 设计:栈及队列(栈实现队列,队列实现栈,最小栈设计; 爬虫系统,微博。
  13. 几种树:b,b+, 二叉树,bst,红黑树,平衡树,234树。

 

数据结构知识点总结

#数组和链表的区别

数组能够处理一组数据类型相同的数据,但不容许动态定义数组的大小,在使用以前必须肯定数组的长度,而链表能够动态分配。linux

逻辑结构上看,数组必须固定长度,不能适应数据动态增减的状况,容易溢出或内存浪费;链表可适应数据动态增减,且能够方便插入、删除。ios

内存角度来看,数组从栈中分配空间(用new则在堆上建立),对程序员方便快速,可是自由度小;链表从堆中分配空间,自由度大可是申请管理比较麻烦。c++

从访问方式类看,数组在内存中是连续的存储,所以能够利用下标索引进行访问;链表是链式存储结构,在访问元素时候只可以经过线性方式由前到后顺序的访问,因此访问效率比数组要低。程序员

#Struct和class的区别

在C++中,Struct和class同样能包含成员函数,可以继承多态。区别在于算法

  1. Struct默认继承访问权限是public而class是private。

默认是public继承仍是private继承取决于子类而不是基类sql

struct能够继承class,一样class也能够继承struct,那么默认的继承访问权限是看子类究竟是用的struct仍是class。以下:shell

 struct A{};class B : A{}; //private继承
struct C : B{}; //public继承数据库

  1. struct做为数据结构的实现体,它默认的数据访问控制是public的,而class做为对象的实现体,它默认的成员变量访问控制是private的
  2. “class”这个关键字还用于定义模板参数,就像“typename”。但关键字“struct”不用于定义模板参数。

#进程和线程的区别

进程是具备必定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.线程是进程的一个实体,CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程本身基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),可是它可与同属一个进程的其余的线程共享进程所拥有的所有资源.一个线程能够建立和撤销另外一个线程;同一个进程中的多个线程之间能够并发执行.

进程和线程的主要差异在于它们是不一样的操做系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不一样执行路径。线程有本身的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,因此多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行而且又要共享某些变量的并发操做,只能用线程,不能用进程。

进程间通讯方式

  1. 管道(pipe,流管道(s_pipe)和有名管道(FIFO):管道是一种半双工的通讯方式,数据只能单向流动,并且只能在具备亲缘关系的进程间使用。进程的亲缘关系一般是指父子进程关系。有名管道容许无亲缘关系进程间的通讯。
  2. 信号(signal):信号是一种比较复杂的通讯方式,用于通知接收进程某个事件已经发生。
  3. 消息队列:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
  4. 共享内存:共享内存就是映射一段能被其余进程所访问的内存,这段共享内存由一个进程建立,但多个进程均可以访问。共享内存是最快的 IPC 方式,它是针对其余进程间通讯方式运行效率低而专门设计的。它每每与其余通讯机制,如信号两,配合使用,来实现进程间的同步和通讯
  5. 信号量(semophore):信号量是一个计数器,能够用来控制多个进程对共享资源的访问。它常做为一种锁机制,防止某进程正在访问共享资源时,其余进程也访问该资源。所以,主要做为进程间以及同一进程内不一样线程之间的同步手段。
  6. 套接字(socket):套解口也是一种进程间通讯机制,与其余通讯机制不一样的是,它可用于不一样及其间的进程通讯

http://blog.csdn.net/gatieme/article/details/50908749

线程间通讯方式

  1. 锁机制:包括互斥锁、条件变量、读写锁
       *互斥锁提供了以排他方式防止数据结构被并发修改的方法。
       *读写锁容许多个线程同时读共享数据,而对写操做是互斥的。
       *条件变量能够以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一块儿使用。
  2. 信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
  3. 信号机制(Signal):相似进程间的信号处理
        线程间的通讯目的主要是用于线程同步,因此线程没有像进程通讯中的用于数据交换的通讯机制。

 

#TCP/UDP

Tcp与udp区别

TCP提供可靠的通讯传输,而UDP则常被用于让广播和细节控制交给应用的通讯传输。

TCP充分实现数据传输时各类控制功能,能够进行丢包的重发控制,还能够对次序乱掉的分包进行顺序控制。而这些在UDP中都没有。此外,TCP做为一种面向有链接的协议,只有在确认通讯对端存在时才会发送数据,从而能够控制通讯流量的浪费。TCP经过检验和、序列号、确认应答、重发控制、链接管理以及窗口控制等机制实现可靠性传输。

TCP用于在传输层有必要实现可靠性传输的状况。因为它是面向有链接并具有顺序控制、重发控制等机制的。因此它能够为应用提供可靠传输。另外一方面,UDP主要用于那些对高速传输和实时性有较高要求的通讯或广播通讯。

TCP与UDP区别总结:

一、TCP面向链接(如打电话要先拨号创建链接);UDP是无链接的,即发送数据以前不须要创建链接

二、TCP提供可靠的服务。也就是说,经过TCP链接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付

三、TCP面向字节流,其实是TCP把数据当作一连串无结构的字节流;UDP是面向报文的。UDP没有拥塞控制,所以网络出现拥塞不会使源主机的发送速率下降(对实时应用颇有用,如IP电话,实时视频会议等)

四、每一条TCP链接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通讯

五、TCP首部开销20字节;UDP的首部开销小,只有8个字节

六、TCP的逻辑通讯信道是全双工的可靠信道,UDP则是不可靠信道

 

UDP实现可靠传输

1. RUDP(Reliable UDP)

可靠用户数据报协议(RUDP)是一种基于可靠数据协议(RDP)的简单分组传输协议,用于传输 IP 网络间的电话信号。RUDP 提供一组数据服务质量加强机制,如拥塞控制的改进、重发机制及淡化服务器算法等,从而在包丢失和网络拥塞的状况下, RTP 客户机(实时位置)面前呈现的就是一个高质量的 RTP 流。在不干扰协议的实时特性的同时,可靠 UDP 的拥塞控制机制容许 TCP 方式下的流控制行为。为了与网络 TCP 通讯量同时工做, RUDP 使用相似于 TCP 的重发机制和拥塞控制算法

2. RTPReal Time Protocol

RTP,实时协议被用来为应用程序如音频,视频等的实时数据的传输提供端到端(end to end)的网络传输功能。传输的模型能够是单点传送或是多点传送。数据传输被一个姐妹协议——实时控制协议(RTCP)来监控,后者容许在一个大的多点传送网络上监视数据传送,而且提供最小限度的控制和识别功能。

3. UDT (UDP-based Data Transfer Protocol,简称UDT)

基于UDP的数据传输协议是一种互联网数据传输协议。UDT的主要目的是支持高速广域网上的海量数据传输,而互联网上的标准数据传输协议TCP在高带宽长距离网络上性能不好。 顾名思义,UDT建于UDP之上,并引入新的拥塞控制和数据可靠性控制机制。UDT是面向链接的双向的应用层协议。它同时支持可靠的数据流传输和部分可靠的数据报传输。 因为UDT彻底在UDP上实现,它也能够应用在除了高速数据传输以外的其它应用领域,例如点到点技术(P2P),防火墙穿透,多媒体数据传输等等。

#琐碎知识点

用户态切换到内核态的方法

系统调用、异常、中断。

Ps:用户态的程序能够经过三种方式访问内核态的资源:系统调用、库函数、shell脚本。

 

局部变量可否和全局变量重名?

答:能,局部会屏蔽全局。要用全局变量,须要使用"::" 。局部变量能够与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内能够定义多个同名的局部变量,好比在两个循环体内都定义一个同名的局部变量,而那个局部变量的做用域就在那个循环体内

如何引用一个已经定义过的全局变量?

答:extern 。能够用引用头文件的方式,也能够用extern关键字,若是用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那个变写错了,那么在编译期间会报错,若是你用extern方式引用时,假定你犯了一样的错误,那么在编译期间不会报错,而在链接期间报错。

 

算法知识点总结

链表反转

使用3个指针遍历单链表,逐个连接点进行反转


操做系统

#死锁

  1. 什么是死锁

所谓死锁,是指多个进程循环等待它方占有的资源而无限期地僵持下去的局面。eg: 进程A占有资源R1,等待进程B占有的资源Rr;进程B占有资源Rr,等待进程A占有的资源R1。并且资源R1和Rr只容许一个进程占用,即:不容许两个进程同时占用。结果,两个进程都不能继续执行,若不采起其它措施,这种循环等待情况会无限期持续下去,就发生了进程死锁。

  1. 死锁产生的缘由

计算机系统产生死锁的根本缘由就是资源有限且操做不当。即一种缘由是系统提供的资源太少了,远不能知足并发进程对资源的需求。另外一种缘由是因为进程推动顺序不合适引起的死锁。

  1. 产生死锁的必要条件

计算机系统只有同时具有如下四个条件才会发生死锁。

〈1〉互斥条件。即某个资源在一段时间内只能由一个进程占有,不能同时被两个或两个以上的进程占有。这种独占资源如CD-ROM驱动器,打印机等等,必须在占有该资源的进程主动释放它以后,其它进程才能占有该资源。这是由资源自己的属性所决定的。如独木桥就是一种独占资源,两方的人不能同时过桥。

  〈2〉不可抢占条件。进程所得到的资源在未使用完毕以前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放。如过独木桥的人不能强迫对方后退,也不能非法地将对方推下桥,必须是桥上的人本身过桥后空出桥面(即主动释放占有资源),对方的人才能过桥。

  〈3〉占有且申请条件。进程至少已经占有一个资源,但又申请新的资源;因为该资源已被另外进程占有,此时该进程阻塞;可是,它在等待新资源之时,仍继续占用已占有的资源。还以过独木桥为例,甲乙两人在桥上相遇。甲走过一段桥面(即占有了一些资源),还须要走其他的桥面(申请新的资源),但那部分桥面被乙占有(乙走过一段桥面)。甲过不去,前进不能,又不后退;乙也处于一样的情况。

  〈4〉循环等待条件。存在一个进程等待序列{P1,P2,...,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一源,......,而Pn等待P1所占有的的某一资源,造成一个进程循环等待环。就像前面的过独木桥问题,甲等待乙占有的桥面,而乙又等待甲占有的桥面,从而彼此循环等待。

  1. 死锁的预防

1)打破互斥条件。容许进程同时访问某些资源,不可取。

2)打破不可抢占条件。容许进程强行从占有者那里夺取某些资源,实现困难下降性能。

3)打破占有且申请条件。能够实行资源预先分配策略。即进程在运行前一次性地向系统申请它所须要的所有资源。若是某个进程所需的所有资源得不到知足,则不分配任何资源,此进程暂不运行。只有当系统可以知足当前进程的所有资源需求时,才一次性地将所申请的资源所有分配给该进程。因为运行的进程已占有了它所需的所有资源,因此不会发生占有资源又申请资源的现象,所以不会发生死锁。可是,这种策略也有以下缺点:

l  在许多状况下,一个进程在执行以前不可能知道它所须要的所有资源。这是因为进程在执行时是动态的,不可预测的;

l  资源利用率低。不管所分资源什么时候用到,一个进程只有在占有所需的所有资源后才能执行。即便有些资源最后才被该进程用到一次,但该进程在生存期间却一直占有它们,形成长期占着不用的情况。这显然是一种极大的资源浪费;

l  下降了进程的并发性。由于资源有限,又加上存在浪费,能分配到所需所有资源的进程个数就必然少了。    

 

#逻辑地址

物理地址:用于内存芯片级的单元寻址,与处理器和CPU链接的地址总线相对应。

逻辑地址:逻辑地址指的是机器语言指令中,用来指定一个操做数或者是一条指令的地址。

线性地址:跟逻辑地址相似,它也是一个不真实的地址,若是逻辑地址是对应的硬件平台段式管理转换前地址的话,那么线性地址则对应了硬件页式内存的转换前地址。

 

C++

#虚函数

virtual在函数中的使用限制

  • 普通函数不能是虚函数,也就是说这个函数必须是某一个类的成员函数,不能够是一个全局函数,不然会致使编译错误。
  • 静态成员函数不能是虚函数, static成员函数是和类同生共处的,他不属于任何对象,使用virtual也将致使错误。
  • 内联函数不能是虚函数 若是修饰内联函数 若是内联函数被virtual修饰,计算机会忽略inline使它变成存粹的虚函数。
  • 构造函数不能是虚函数,不然会出现编译错误。

虚函数表指针

类中除了定义的函数成员,还有一个成员是虚函数表指针(占四个基本内存单元),这个指针指向一个虚函数表的起始位置,这个表会与类的定义同时出现,这个表存放着该类的虚函数指针,调用的时候能够找到该类的虚函数表指针,经过虚函数表指针找到虚函数表,经过虚函数表的偏移找到函数的入口地址,从而找到要使用的虚函数。

父类和子类出现同名函数称为隐藏。父类和子类出现同名虚函数称为覆盖。

虚析构函数

特色:当咱们在父类中经过virtual修饰析构函数以后,经过父类指针指向子类对象,经过delete接父类指针就能够释放掉子类对象。

解决问题:经过父类指针操做子类对象的成员函数的时候是没有问题的,但是在销毁对象内存的时候则只是执行了父类的析构函数,子类的析构函数却没有执行,这会致使内存泄漏,即多态中的内存泄漏问题。

原理:若是父类当中定义了虚析构函数,那么父类的虚函数表当中就会有一个父类的虚析构函数的入口指针,指向的是父类的虚析构函数,子类虚函数表当中也会产生一个子类的虚析构函数的入口指针,指向的是子类的虚析构函数,这个时候使用父类的指针指向子类的对象,delete接父类指针,就会经过指向的子类的对象找到子类的虚函数表指针,从而找到虚函数表,再虚函数表中找到子类的虚析构函数,从而使得子类的析构函数得以执行,子类的析构函数执行以后系统会自动执行父类的虚析构函数。这个是虚析构函数的实现原理。

纯虚函数

class Shape

{

public:

    virtual  double calcArea()//虚函数

    {....}

    virtual  double calcPerimeter()=0;//纯虚函数

    ....

};

纯虚函数没有函数体,同时在定义的时候函数名后面要加“=0”。

纯虚函数的实现原理:

      在虚函数原理的基础上,虚函数表中,虚函数的地址是一个有意义的值,若是是纯虚函数就实实在在的写一个0。

含有纯虚函数的类被称为抽象类,纯虚函数没有函数体,因此抽象类不容许实例化对象,而对于一些具体的类来讲,咱们要求必须实现那些要求(纯虚函数),使之成为有具体动做的类。抽象类的子类也能够是一个抽象类。抽象类子类只有把抽象类当中的全部的纯虚函数都作了实现才能够实例化对象。

若是在抽象类当中仅含有纯虚函数而不含其余任何东西,咱们称之为接口类

  1. 没有任何数据成员
  2. 仅有成员函数
  3. 成员函数都是纯虚函数

虚函数和纯虚函数的区别

l  类里声明为虚函数的话,这个函数是实现的,哪怕是空实现,它的做用就是为了能让这个函数在它的子类里面能够被重载,这样的话,这样编译器就可使用后期绑定来达到多态了;纯虚函数只是一个接口,是个函数的声明而已,它要留到子类里去实现。

l  虚函数在子类里面也能够不重载的;但纯虚必须在子类去实现,这就像Java的接口同样。一般咱们把不少函数加上virtual,是一个好的习惯,虽然牺牲了一些性能,可是增长了面向对象的多态性,由于你很难预料到父类里面的这个函数不在子类里面不去修改它的实现。

l  虚函数的类用于“实做继承”,继承接口的同时也继承了父类的实现。固然咱们也能够完成本身的实现。纯虚函数的类用于“介面继承”,主要用于通讯协议方面。关注的是接口的统一性,实现由子类完成。通常来讲,介面类中只有纯虚函数的。

#类的内存计算(sizeof)

相关文章
相关标签/搜索