鵝廠cpp linux後臺服務器開發崗面試總結(含答案)

一、堆和棧的區別

堆空間的內存是動態分配的,通常存放對象,而且須要手動釋放內存malloc()/free()或new/delete。linux

棧空間的內存是由系統自動分配,通常存放局部變量,好比對象的地址等值,不須要程序員對這塊內存進行管理,好比,函數中的局部變量的做用範圍(生命週期)就是在調完這個函數以後就結束了。程序員

二、free/delete與malloc/free區別

  1. new分配內存按照數據類型進行分配,malloc分配內存按照指定的大小分配;
  2. new不只分配一段內存,並且會調用構造函數,malloc不會。(面試官強調)
  3. new分配的內存要用delete銷燬,malloc要用free來銷燬;delete銷燬的時候會調用對象的析構函數,而free則不會。(面試官強調)
  4. new返回的是指定對象的指針,而malloc返回的是void*,所以malloc的返回值通常都須要進行類型轉化。
  5. new是一個操做符能夠重載,malloc是一個庫函數。
  6. malloc分配的內存不夠的時候,能夠用realloc擴容。擴容的原理?new沒用這樣操做。
  7. new若是分配失敗了會拋出bad_malloc的異常,而malloc失敗了會返回NULL。
  8. 申請數組時: new[]一次分配全部內存,屢次調用構造函數,搭配使用delete[],delete[]屢次調用析構函數,銷燬數組中的每一個對象。而malloc則只能sizeof(int) * n。

三、指針常量與常量指針

鵝廠cpp linux後臺服務器開發崗面試總結(含答案)

指針常量——指針類型的常量(int *const p)。本質上一個常量,指針用來講明常量的類型,表示該常量是一個指針類型的常量。在指針常量中,指針自身的值是一個常量,不可改變,始終指向同一個地址。在定義的同時必須初始化。golang

常量指針——指向「常量」的指針(const int p, int const p)。常量指針本質上是一個指針,常量表示指針指向的內容,說明該指針指向一個「常量」。在常量指針中,指針指向的內容是不可改變的,指針看起來好像指向了一個常量。面試

須要C/C++ Linux高級服務器架構師學習資料後臺加羣812855908(包括C/C++,Linux,golang技術,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK,ffmpeg等)編程

淺析Linux中徹底公平調度——CFS

四、指針與引用的區別

  1. 指針有本身的一塊空間,而引用只是一個別名;
  2. 使用sizeof看一個指針的大小是4,而引用則是被引用對象的大小;
  3. 指針能夠被初始化爲NULL,而引用必須被初始化且必須是一個已有對象 的引用;
  4. 做爲參數傳遞時,指針須要被解引用才能夠對對象進行操做,而直接對引 用的修改都會改變引用所指向的對象;
  5. 能夠有const指針,可是沒有const引用;
  6. 指針在使用中能夠指向其它對象,可是引用只能是一個對象的引用,不能被改變;(面試官強調)
  7. 指針能夠有多級指針(**p),而引用至於一級;
  8. 指針和引用使用++運算符的意義不同;
  9. 若是返回動態內存分配的對象或者內存,必須使用指針,引用可能引發內存泄露。

五、struct與union數據內存對齊,內存對齊的做用

鵝廠cpp linux後臺服務器開發崗面試總結(含答案)

結構體struct內存對齊的3大規則:數組

  1. 對於結構體的各個成員,第一個成員的偏移量是0,排列在後面的成員其當前偏移量必須是當前成員類型的整數倍;
  2. 結構體內全部數據成員各自內存對齊後,結構體自己還要進行一次內存對齊,保證整個結構體佔用內存大小是結構體內最大數據成員的最小整數倍;
  3. 如程序中有#pragma pack(n)預編譯指令,則全部成員對齊以n字節爲準(即偏移量是n的整數倍),再也不考慮當前類型以及最大結構體內類型。
struct CAT_s
{
    int ld;
    char Color;
    unsigned short Age;
    char *Name;
    void(*Jump)(void);
}Garfield;

按照上面的3大規則直接來進行分析:服務器

  1. 使用32位編譯,int佔4, char 佔1, unsigned short 佔2,char* 佔4,函數指針佔4個,因爲是32位編譯是4字節對齊,因此該結構體佔16個字節。(說明:按幾字節對齊,是根據結構體的最長類型決定的,這裏是int是最長的字節,因此按4字節對齊);
  2. 使用64位編譯 ,int佔4, char 佔1, unsigned short 佔2,char* 佔8,函數指針佔8個,因爲是64位編譯是8字節對齊,(說明:按幾字節對齊,是根據結構體的最長類型決定的,這裏是函數指針是最長的字節,因此按8字節對齊)因此該結構體佔24個字節。

聯合體union內存對齊的2大規則:數據結構

  1. 找到佔用字節最多的成員;
  2. union的字節數必須是佔用字節最多的成員的字節的倍數,並且須要可以容納其餘的成員.
//x64
typedef union {
    long i;
    int k[5];
    char c;
}D

要計算union的大小,首先要找到佔用字節最多的成員,本例中是long,佔用8個字節,int k[5]中都是int類型,仍然是佔用4個字節的,而後union的字節數必須是佔用字節最多的成員的字節的倍數,並且須要可以容納其餘的成員,爲了要容納k(20個字節),就必需要保證是8的倍數的同時還要大於20個字節,因此是24個字節。架構

內存對齊做用:併發

  1. 平臺緣由(移植緣由):不是全部的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特定類型的數據,不然拋出硬件異常。
  2. 性能緣由:數據結構(尤爲是棧)應該儘量地在天然邊界上對齊。緣由在於,爲了訪問未對齊的內存,處理器須要做兩次內存訪問;而對齊的內存訪問僅須要一次訪問。

六、TCP與UDP協議區別,具體的底層協議,屬於哪一層,TCP握手協議的實現

鵝廠cpp linux後臺服務器開發崗面試總結(含答案)

TCP與UDP屬於傳輸層

七、說出本身經常使用的容器,並給出經常使用的一些標準庫用法

vector stack queue set

八、map容器(面試官強調)

C++ map用法參考連接

九、map與hush_map區別

hash_map和map的區別參考連接

十、給你一億個數據如何統計IP地址出現的次數

因爲電腦內存不夠,因此不能一次將數據所有讀取,只能實行分而治之的方法,才能知足空間的需求。能夠建立一個hash表,將數據按必定的Key value分類,可使用了將IP轉化成長整形,而後取其後三位轉化成字符串做爲Key value,這樣就能將全部IP按後三位分類。

十一、vector與list的區別,以及各類操做的複雜度

1.概念

1)vector:

連續存儲的容器,動態數組,在堆上分配空間。

底層實現:數組。

兩倍容量增加:vector 增長(插入)新元素時,若是未超過當時的容量,則還有剩餘空間,那麼直接添加到最後(插入指定位置),而後調整迭代器。若是沒有剩餘空間了,則會從新配置原有元素個數的兩倍空間,而後將原空間元素經過複製的方式初始化新空間,再向新空間增長元素,最後析構並釋放原空間,以前的迭代器會失效。

性能:

訪問:時間複雜度O(1)

插入:在最後插入(空間夠):很快。時間複雜度O(1)。

在最後插入(空間不夠):須要內存申請和釋放,以及對以前數據進行拷貝。時間複雜度O(n)。

在中間插入(空間夠):內存拷貝

在中間插入(空間不夠):須要內存申請和釋放,以及對以前數據進行拷貝。

刪除:在最後刪除:很快。

在中間刪除:內存拷貝。

適用場景:常常隨機訪問,且不常常對非尾節點進行插入刪除。

2)list:

動態鏈表,在堆上分配空間,每插入一個元數都會分配空間,每刪除一個元素都會釋放空間。

底層:雙向鏈表。

性能:

訪問:隨機訪問性能不好,只能快速訪問頭尾節點。

插入:很快,通常是常數開銷。

刪除:很快,通常是常數開銷。

適用場景:常常插入刪除大量數據。

2.區別

  1. vector底層實現是數組;list是雙向 鏈表。
  2. vector支持隨機訪問,list不支持。
  3. vector是順序內存,list不是。
  4. vector在中間節點進行插入刪除會致使內存拷貝,list不會。
  5. vector一次性分配好內存,不夠時才進行2倍擴容;list每次插入新節點都會進行內存申請。
  6. vector隨機訪問性能好,插入刪除性能差;list隨機訪問性能差,插入刪除性能好。

3.應用

vector擁有一段連續的內存空間,所以支持隨機訪問,若是須要高效的隨即訪問,而不在意插入和刪除的效率,使用vector。

list擁有一段不連續的內存空間,若是須要高效的插入和刪除,而不關心隨機訪問,則應使用list。

十二、排序,以及排序代碼實現邏輯,以及複雜度。

鵝廠cpp linux後臺服務器開發崗面試總結(含答案)

1三、覆蓋與重載的區別。

重載:兩個函數名相同,可是參數列表不一樣(個數,類型),返回值類型沒有要求,在同一做用域中。

重載的實現是:編譯器根據函數不一樣的參數表,對同名函數的名稱作修飾,而後這些同名函數就成了不一樣的函數(至少對於編譯器來講是這樣的)。如,有兩個同名函數:function func(p:integer):integer;和function func(p:string):integer;。那麼編譯器作過修飾後的函數名稱多是這樣的:int_func、str_func。對於這兩個函數的調用,在編譯器間就已經肯定了,是靜態的(記住:是靜態)。也就是說,它們的地址在編譯期就綁定了(早綁定),所以,重載和多態無關!

覆蓋:子類繼承了父類,父類中的函數是虛函數,在子類中從新定義了這個虛函數

真正和多態相關的是「覆蓋」。當子類從新定義了父類的虛函數後,父類指針根據賦給它的不一樣的子類指針,動態(記住:是動態!)的調用屬於子類的該函數,這樣的函數調用在編譯期間是沒法肯定的(調用的子類的虛函數的地址沒法給出)。所以,這樣的函數地址是在運行期綁定的(晚邦定)。結論就是:重載只是一種語言特性,與多態無關,與面向對象也無關!引用一句Bruce Eckel的話:「不要犯傻,若是它不是晚邦定,它就不是多態。」

1四、進程與線程的區別。

1.基本概念:

進程是對運行時程序的封裝,是系統進行資源調度和分配的的基本單位,實現了操做系統的併發;

線程是進程的子任務,是CPU調度和分派的基本單位,用於保證程序的實時性,實現進程內部的併發;線程是操做系統可識別的最小執行和調度單位。每一個線程都獨自佔用一個虛擬處理器:獨自的寄存器組,指令計數器和處理器狀態。每一個線程完成不一樣的任務,可是共享同一地址空間(也就是一樣的動態內存,映射文件,目標代碼等等),打開的文件隊列和其餘內核資源。

2.區別:

  1. 一個線程只能屬於一個進程,而一個進程能夠有多個線程,但至少有一個線程。線程依賴於進程而存在。
  2. 進程在執行過程當中擁有獨立的內存單元,而多個線程共享進程的內存。(資源分配給進程,同一進程的全部線程共享該進程的全部資源。同一進程中的多個線程共享代碼段(代碼和常量),數據段(全局變量和靜態變量),擴展段(堆存儲)。可是每一個線程擁有本身的棧段,棧段又叫運行時段,用來存放全部局部變量和臨時變量。)
  3. 進程是資源分配的最小單位,線程是CPU調度的最小單位;
  4. 系統開銷: 因爲在建立或撤消進程時,系統都要爲之分配或回收資源,如內存空間、I/O設備等。所以,操做系統所付出的開銷將顯著地大於在建立或撤消線程時的開銷。相似地,在進行進程切換時,涉及到整個當前進程CPU環境的保存以及新被調度運行的進程的CPU環境的設置。而線程切換隻須保存和設置少許寄存器的內容,並不涉及存儲器管理方面的操做。可見,進程切換的開銷也遠大於線程切換的開銷。
  5. 通訊:因爲同一進程中的多個線程具備相同的地址空間,導致它們之間的同步和通訊的實現,也變得比較容易。進程間通訊IPC,線程間能夠直接讀寫進程數據段(如全局變量)來進行通訊——須要進程同步和互斥手段的輔助,以保證數據的一致性。在有的系統中,線程的切換、同步和通訊都無須操做系統內核的干預
  6. 進程編程調試簡單可靠性高,可是建立銷燬開銷大;線程正相反,開銷小,切換速度快,可是編程調試相對複雜。
  7. 進程間不會相互影響 ;線程一個線程掛掉將致使整個進程掛掉
  8. 進程適應於多核、多機分佈;線程適用於多核

1五、進程間的通訊方式。

進程間通訊主要包括管道、系統IPC(包括消息隊列、信號量、信號、共享內存等)、以及套接字socket(面試官強調)。

1六、讀寫鎖、自旋鎖與死鎖。

讀寫鎖實際是一種特殊的自旋鎖,它把對共享資源的訪問者劃分紅讀者和寫者,讀者只對共享資源進行讀訪問,寫者則須要對共享資源進行寫操做。這種鎖相對於自旋鎖而言,能提升併發性,由於在多處理器系統中,它容許同時有多個讀者來訪問共享資源,最大可能的讀者數爲實際的邏輯CPU數。寫者是排他性的,一個讀寫鎖同時只能有一個寫者或多個讀者(與CPU數相關),但不能同時既有讀者又有寫者。

有了原子操做,就能夠了製做控制臨界區的鎖機制了。自旋鎖就是其中的一個表明。自旋鎖機制能夠用門和鎖的例子來比喻。進程執行到某個臨界區,至關於要進入一棟房子,這是進程會檢查屋內是否有人(進程),若是屋內沒有人,則直接拿起鑰匙進入並把門鎖上(進入臨界區);若是屋內有人(進程),則在門口等待(忙等待)屋內的進程出來再進去。能夠看出,自旋鎖最多隻能被一個進程持有,若是有新的進程但願獲取自旋鎖,它將會一直忙等待直到前一個持有自旋鎖的進程釋放鎖。

在多道程序系統中,因爲多個進程的併發執行,改善了系統資源的利用率並提升了系統 的處理能力。然而,多個進程的併發執行也帶來了新的問題——死鎖。所謂死鎖是指多個進程因競爭資源而形成的一種僵局(互相等待),若無外力做用,這些進程都將沒法向前推動。

相關文章
相關標籤/搜索