找工做知識點總結

  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)

相關文章
相關標籤/搜索