C++ 后端開發(fā)如何規(guī)劃學習路線?
C++ 面試一般考察的內(nèi)容
1. 語言基礎
C++ 虛函數(shù)這是面試初、中級 C++ 職位一個概率 95% 以上的面試題。一般有以下幾種問法:
1.在有繼承關系的父子類中,構建和析構一個子類對象時,父子構造函數(shù)和析構函數(shù)的執(zhí)行順序分別是怎樣的?
2.在有繼承關系的類體系中,父類的構造函數(shù)和析構函數(shù)一定要申明為 virtual 嗎?如果不申明為 virtual 會怎樣?
3.什么是 C++ 多態(tài)?C++ 多態(tài)的實現(xiàn)原理是什么?
4.什么是虛函數(shù)?虛函數(shù)的實現(xiàn)原理是什么?
5.什么是虛表?虛表的內(nèi)存結構布局如何?虛表的第一項(或第二項)是什么?
6.菱形繼承(類 D 同時繼承 B 和 C,B 和 C又繼承自A)體系下,虛表在各個類中的布局如何?如果類B和類C同時有一個成員變了m,m如何在D對象的內(nèi)存地址上分布的?是否會相互覆蓋?
另外,時至今日,你一定要熟悉 C++11/14/17 常用的語言特性和類庫,這里簡單地列一下:
統(tǒng)一的類成員初始化語法與 std::initializer_list
注解標簽(attributes)
final/override/=default/=delete 語法
auto 關鍵字
Range-based 循環(huán)語法
結構化綁定
stl 容器新增的實用方法
std::thread
線程局部存儲 thread_local
線程同步原語 std::mutex、std::condition_variable 等
原子操作類
智能指針類
std::bind/std::function
C++11/14 網(wǎng)上的資料已經(jīng)很多了,C++17 的資料不多,重頭戲還是 C++11 引入的各種實用特性,這就給讀者推薦一本我讀過的:
《深入理解 C++11:C++11 新特性解析與應用》
《深入應用 C++11:代碼優(yōu)化與工程級應用》
《C++17 完全指南》
《Cpp 17 in Detail》
這里網(wǎng)絡上也有人分享出來,下載鏈接:
鏈接: https://pan.baidu.com/s/1Af_6-bkugcTFljpIoeIk7Q 密碼: mltg
建議購買正版哦。
C++11/14/17 的語法雖然很實用,但是需要一定的練習才能掌握,推薦幾個學習 C++11/14/17 的開源項目:
1. filezilla
filezilla 是一款開源的 FTP 軟件,其源碼下載地址如下:
https://svn.filezilla-project.org/svn/FileZilla3/trunk
需要使用 svn 工具來下載,安裝好 svn 工具后,在 svn 界面中 checkout 上述地址或者使用如下命令下載:
svn co https://svn.filezilla-project.org/svn/FileZilla3/trunk filezilla
如果使用 svn 圖形化工具,直接使用以下 svn 地址將源碼 checkout 到指定目錄即可:
https://svn.filezilla-project.org/svn/FileZilla3/trunk
如果你不知道怎么下載,可以直接在“高性能服務器開發(fā)”公眾號回復“獲取Filezilla源碼”進行下載。
2. uWebSocket 網(wǎng)絡庫
uWebSocket 是一款開源的 WebSocket 庫,最新版使用了大量 C++17 的語法,美中不足的是這個庫代碼存在不少 bug,我在項目中使用了它,但修改了其大量的 bug,有興趣的朋友也可以下載下來看一下:
下載地址:
https://github.com/uNetworking/uWebSockets
3. TeamTalk 的 PC 端
TeamTalk 是蘑菇街開源的一款用于企業(yè)內(nèi)部的即時通信工具,其下載地址是:
https://github.com/balloonwj/TeamTalk/tree/master/win-client
4. 最后是我的開源 Flamingo IM
https://github.com/balloonwj/flamingo balloonwj/flamingo
2. 算法與數(shù)據(jù)結構基礎
說到算法和數(shù)據(jù)結構,對于社招人士和對于應屆生一般是不一樣的,對于大的互聯(lián)網(wǎng)公司和一般的小的企業(yè)也是不一樣的。下面根據(jù)我當面試官面試別人和找工作被別人面試經(jīng)驗來談一談。
先說考察的內(nèi)容,除了一些特殊的崗位,常見的算法和數(shù)據(jù)結構面試問題有如下:
1.排序(??嫉呐判虬搭l率考排序為:快速排序 > 冒泡排序 > 歸并排序 > 桶排序)
一般對于對算法基礎有要求的公司,如果你是應屆生或者工作經(jīng)驗在一至三年內(nèi),以上算法如果寫不出來,給面試官的影響會非常不好,甚至直接被 pass 掉。對于工作三年以上的社會人士,如果寫不出來,但是能分析出其算法復雜度、最好和最壞的情況下的復雜度,說出算法大致原理,在多數(shù)面試官面前也可以過的。注意,如果你是學生,寫不出來或者寫的不對,基本上面試過不了。
1.二分查找
二分查找的算法盡量要求寫出來。當然,大多數(shù)面試官并不會直接問你二分查找,而是結合具體的場景,例如如何求一個數(shù)的平方根,這個時候你要能想到是二分查找。我在2017年年底,面試agora時,面試官問了一個問題:如何從所有很多的ip地址中快速找個某個ip地址。
2.鏈表
無論是應屆生還是工作年限不長的社會人士,璉表常見的操作一定要熟練寫出來,如鏈表的查找、定位、反轉、連接等等。還有一些經(jīng)典的問題也經(jīng)常被問到,如兩個鏈表如何判斷有環(huán)(我在2017年面試餓了么二面、上海黃金交易所一面被問過)。鏈表的問題一般不難,但是鏈表的問題存在非常多的“坑”,如很多人不注意邊界檢查、空鏈表、返回一個鏈表的函數(shù)應該返回鏈表的頭指針等等。
3.隊列與棧
對于應屆生來說一般這一類問的比較少,但是對于社會人士尤其是中高級崗位開發(fā),會結合相關的問題問的比較多,例如讓面試者利用隊列寫一個多線程下的生產(chǎn)者和消費者程序,全面考察的多線程的資源同步與競態(tài)問題(下文介紹多線程面試題時詳細地介紹)。棧一般對于基礎要求高的面試,會結合函數(shù)調(diào)用實現(xiàn)來問。即函數(shù)如何實現(xiàn)的,包括函數(shù)的調(diào)用的幾種常見調(diào)用方式、參數(shù)的入棧順序、內(nèi)存棧在地址從高向低擴展、棧幀指針和棧頂指針的位置、函數(shù)內(nèi)局部變量在棧中的內(nèi)存分布、函數(shù)調(diào)用結束后,調(diào)用者和被調(diào)用者誰和如何清理棧等等。某年面試京東一基礎部門,面試官讓寫從0加到100這樣一個求和算法,然后寫其匯編代碼。
4.哈希表
哈希表是考察最多的數(shù)據(jù)結構之一。常見的問題有哈希沖突的檢測、讓面試者寫一個哈希插入函數(shù)等等?;旧弦粓雒嬖囅聛聿豢疾旒t黑樹基本上就會問哈希表,而且問題可淺可深。我印象比較深刻的是,當年面試百度廣告推薦部門時,二面問的一些關于哈希表的問題。當時面試官時先問的鏈表,接著問的哈希沖突的解決方案,后來讓寫一個哈希插入算法,這里需要注意的是,你的算法中插入的元素一定要是通用元素,所以對于 C++ 或者 Java 語言,一定要使用模板這一類參數(shù)作為哈希插入算法的對象。然后,就是哈希表中多個元素沖突時,某個位置的元素使用鏈表往后穿成一串的方案。最終考察 linux 下 malloc(下面的ptmalloc) 函數(shù)在頻繁調(diào)用造成的內(nèi)存碎片問題,以及開源方案解決方案 tcmalloc 和 jemalloc。總體下來,面試官是一步步引導你深入。(有興趣的讀者可以自行搜索,網(wǎng)上有很多相關資料)
5.樹
面試高頻的樹是紅黑樹,也有一部分是B樹(B+樹)。紅黑樹一般的問的深淺不一,大多數(shù)面試官只要能說出紅黑樹的概念、左旋右旋的方式、分析出查找和插入的平均算法復雜度和最好最壞時的算法復雜度,并不要寫面試者寫出具體代碼實現(xiàn)。一般 C++ 面試問 stl 的map,java 面試問 TreeMap 基本上就等于開始問你紅黑樹了,要有心里準備。筆者曾經(jīng)面試愛奇藝被問過紅黑樹。B樹一般不會直接問,問的最多的形式是通過問 MySQL 索引實現(xiàn)原理(數(shù)據(jù)庫知識點將在下文中討論)。筆者面試騰訊看點部門二面被問到過。
6.圖
圖的問題就我個人面試從來沒遇到過,不過據(jù)我某位哥哥所說,他在進三星電子之前有一道面試題就是深度優(yōu)先和廣度優(yōu)先問題。
7.其他的一些算法
如 A*尋路、霍夫曼編碼也偶爾會在某一個領域的公司的面試中被問到。
3. 編碼基本功
還有一類面試題不好分類,筆者姑且將其當作是考察編碼基本功,這類問題既可以考察算法也可以考察你寫代碼基本素養(yǎng),這些素養(yǎng)不僅包括編碼風格、計算機英語水平、調(diào)試能力等,還包括你對細節(jié)的掌握和易錯點理解,如有意識地對邊界條件的檢查和非法值的過濾。請讀者看以下的代碼執(zhí)行結果是什么?
for(char?i?=?0;?i?<?256;?++i)?
{
? ?printf("%d\n",?i);
}
下面再列舉幾個常見的編碼題:
(1)實現(xiàn)一個 memmov 函數(shù) 這個題目考查點在于 memmov 函數(shù)與 memcpy 函數(shù)的區(qū)別,這兩者對于源地址與目標地址內(nèi)存有重疊的這一情況的處理方式是不一樣的。
(2)實現(xiàn) strcpy 或 strncpy 函數(shù),這類函數(shù)寫出來沒啥難度,但是一定要注意邊界條件檢查,還有就是其返回值一定要是目標內(nèi)存地址,以支持所謂的鏈式拷貝。這兩類細節(jié)沒考慮到基本上算不通過。
即:
strcpy(dest3,?strcpy(dest2,?strcpy(dest1,?src1)));
(3)實現(xiàn)atoi函數(shù) 這個函數(shù)的簽名如下:
int?atoi(const?char*?p);
容易疏忽的地方有如下幾點:
小數(shù)點問題,如數(shù)字 0.123 和 .123 都是合法的;
正負號問題,如 +123 和 -123;
考慮如何識別第一個非法字符問題,如 123Z89,則應轉換成應該 123。
4. 多線程開發(fā)基礎
現(xiàn)如今的多核 CPU 早已經(jīng)是司空見慣,而多線程編程早已經(jīng)是“飛入尋常百姓家”。對于大多數(shù)桌面應用(與 Web 開發(fā)相對),尤其是像后臺開發(fā)這樣的崗位,且面試者是社會人員(有一定的工作經(jīng)驗),如果面試者不熟悉多線程編程,那么一般會被直接 pass 掉。
這里說的?“熟悉多線程編程”?到底熟悉到什么程度呢?一般包括:知道何種場合下需要新建新的線程、線程如何創(chuàng)建和等待、線程與進程的關系、線程局部存儲(TLS 或者叫 thread local)、多線程訪問資源產(chǎn)生競態(tài)的原因和解決方案等等、熟練使用所在操作系統(tǒng)平臺提供的線程同步的各種原語。
對于 C++ 開發(fā)者,你需要:
對于 Windows 開發(fā)者,你需要熟練使用 Interlock系列函數(shù)、CriticalSection、Event、Mutex、Semphore等API 函數(shù)和兩個重要的函數(shù) WaitForSingleObject、WaitForMultipleObjects。
對于 Linux 開發(fā)者,你需要熟練使用 mutex、semphore、condition_variable、read-write-lock 等操作系統(tǒng)API。
可以使用 C++ 實現(xiàn)一個簡單的線程池,當然支持優(yōu)先級、動態(tài)創(chuàng)建線程功能就更好了。
5. 數(shù)據(jù)庫
數(shù)據(jù)庫知識一般在大的互聯(lián)網(wǎng)企業(yè)對應屆生不做硬性要求,對于小的互聯(lián)網(wǎng)企業(yè)或社會人士一般有一定的要求。其要求一般包括:
(1)熟悉基本 SQL 操作 包括增刪改查(insert、delete、update、select語句),排序 order,條件查詢(where 子語句),限制查詢結果數(shù)量(LIMIT語句)等
(2)稍微高級一點的 SQL 操作(如 Group by,in,join,left join,多表聯(lián)合查詢,別名的使用,select 子語句等)
(3)索引的概念、索引的原理、索引的創(chuàng)建技巧
(4)數(shù)據(jù)庫本身的操作,建庫建表,數(shù)據(jù)的導入導出
(5)數(shù)據(jù)庫用戶權限控制(權限機制)
(6)MySQL的兩種數(shù)據(jù)庫引擎的區(qū)別
(7)SQL 優(yōu)化技巧
以上屬于對開發(fā)的基本的數(shù)據(jù)庫知識要求,你可以找一本相關入門級的數(shù)據(jù)庫圖書學習即可。
高級開發(fā)除了以上要求還要熟悉高可用?MySQL、主從同步、讀寫分離、分表分庫?等技術,這些技術的細節(jié)一定要清楚,它們是你成為技術專家或者高級架構的必備知識。
我們在實際面試時,在討論高可用服務服務方案時,很多面試者也會和我們討論到這些技術,但是不少面試者只知道這些技術的大致思想,細節(jié)往往說不清楚,細節(jié)不會就意味著你的高可用方案無法落地,企業(yè)需要可以落地的方案。
這些技術我首推?《高性能 MySQL》?這本書,這本書高級開發(fā)者一定要通讀的,另外還有 2 本非常好的圖書也推薦一下:一本是?《MySQL 排錯指南》,?讀完這本書以后,你會對整個“數(shù)據(jù)庫世界”充滿了清晰的認識;另外一本是?《數(shù)據(jù)庫索引設計與優(yōu)化》,?這本書讀起來非常舒服,尤其是對于喜歡算法和數(shù)據(jù)結構的同學來說。
網(wǎng)上也有同學整理分享出來,下載鏈接(喜歡記得買正版哦):
鏈接: https://pan.baidu.com/s/1mCTqrOXkpsRbEpPK-lmrVg ?密碼: foqu
6. 網(wǎng)絡編程
網(wǎng)絡編程這一塊,對于應屆生或者初級崗位一般只會問一些基礎網(wǎng)絡通信原理(如三次握手和四次揮手)的 socket ?基礎 API 的使用,客戶端與服務器端網(wǎng)絡通信的流程(回答 【客戶端創(chuàng)建 socket -> 連接 server ->收發(fā)數(shù)據(jù);服務器端創(chuàng)建 socket -> 綁定 IP 和端口號 -> 啟動偵聽 ->接受客戶端連接 ->與客戶端通信收發(fā)數(shù)據(jù)】即可)、TCP 與 UDP 的區(qū)別等等。
對于工作經(jīng)驗三年以內(nèi)的社會人士或者一些中級面試者一般會問一些稍微重難點問題,如 select 函數(shù)的用法,非阻塞 connect 函數(shù)的寫法,epoll 的水平和邊緣模式、阻塞socket與非阻塞 socket 的區(qū)別、send/recv 函數(shù)的返回值情形、REUSE_ADDR 選項等等。Windows 平臺可能還會問 WSAEventSelect 和 WSAAsyncSelect 函數(shù)的用法、完成端口(IOCP 模型)。
對于三年以上尤其是“號稱”自己設計過服務器、看過開源網(wǎng)絡通信庫代碼的面試者,面試官一般會深入問一些問題,這類問題要么是實際項目中常見的難題或者網(wǎng)絡通信細節(jié),根據(jù)我的經(jīng)驗,一般有這樣一些問題:
1.nagle 算法;
2.keepalive 選項;
3.Linger 選項;
4.對于某一端出現(xiàn)大量 CLOSE_WAIT 或者 TIME_WAIT 如何解決;
5.通訊協(xié)議如何設計或如何解決數(shù)據(jù)包的粘包與分片問題;
6.心跳機制如何設計;(可能不會直接問問題本身,如問如何檢查死鏈)
7.斷線重連機制如何設計;
8.對 IO Multiplexing 技術的理解;
9.收發(fā)數(shù)據(jù)包正確的方式,收發(fā)緩沖區(qū)如何設計;
10.優(yōu)雅關閉;
11.定時器如何設計;
12.epoll 的實現(xiàn)原理。
舉兩個例子,讓讀者感受一下:
B 站面試曾被問的一個問題:如果 A 機器與 B 機器網(wǎng)絡 connect 成功后從未互發(fā)過數(shù)據(jù),此時其中一機器突然斷電,則另外一臺機器與斷電的機器之間的網(wǎng)絡連接處于哪種狀態(tài)?
7. 內(nèi)存數(shù)據(jù)庫&緩存技術
時下以 NoSql key-value 為思想的內(nèi)存數(shù)據(jù)庫大行其道,廣泛地用于各種后臺項目開發(fā)。所以?熟悉一種或幾種內(nèi)存數(shù)據(jù)庫程序已經(jīng)是面試后臺開發(fā)的基本要求,?而這當中以 Redis 為最典型代表,這里以 Redis 為例。
第一層面一般是對 Redis 的基礎用法的考察 如考察 Redis 支持的基礎數(shù)據(jù)類型、Redis的數(shù)據(jù)持久化、事務等。
第二層面不僅考察 Redis 的基礎用法,還會深入到 Redis 源碼層面上,如 Redis 的網(wǎng)絡通信模型、Redis 各種數(shù)據(jù)結構的實現(xiàn)等等。
Redis 高可用技術、cluster、哨兵策略等。
筆者以為,無論是從找工作應付面試還是從提高技術的角度,Redis 是一個非常值得學習的開源軟件,希望廣大讀者有意識地去了解、學習它。
另外一些像分布式、RPC、MQ 等技術和 C++ 本身關系不是很緊密,這里就不羅列了。
8. 項目經(jīng)驗
除了社會招聘和一些小型的企業(yè),一般的大型互聯(lián)網(wǎng)公司對應屆生不會做過多的項目經(jīng)驗要求,而是希望他們算法與數(shù)據(jù)結構等基礎扎實、動手實踐能力強即可。對于一般的小公司,對于應屆生會要求其至少熟練使用一門編程語言以及相應的開發(fā)工具,號稱熟悉 Linux C++ 開發(fā)的面試者,不熟悉 GDB 調(diào)試基本上不是真正的熟悉 Linux C++ 開發(fā);號稱熟悉匯編或者反匯編,不熟悉 IDA 或者 OllyDbg,基本上也是名不符實的;號稱熟悉 VC++ 開發(fā),連 F8、F9、F10、F11、F12 等快捷鍵不熟悉也是難以經(jīng)得住面試官的提問的。受疫情影響,很多面試都改成了線上面試,當你寫算法題時如果你對開發(fā)工具不熟悉,面試官基本一下子就能看出來。?這點請大家注意。
這里給一些學歷不算好,學校不是非常有名,尤其是二本以下的廣大想進入 IT 行業(yè)的同學一個建議,在大學期間除了要學好計算機專業(yè)基礎知識以外,一定要熟練使用一門編程語言以及相應的開發(fā)工具。
關于項目經(jīng)驗,許多面試者認為一定要是自己參與的項目,其實也可以來源于你學習和閱讀他人源碼或開源軟件的源碼,如果你能理解并掌握這些開源軟件中的思想和技術,在面試的時候能夠與面試官侃侃而談,面試官也會非常滿意的。
很多同學可能糾結大學或者研究生期間要不要跟著導師做一些項目。當然,如果這些項目是課程要求,那么你必須得參加;如果這些項目是可以選擇性的,尤其是一些僅僅拿著第三方的庫進行所謂的包裝和加工,那么建議可以少參加一些。
另外,大廠面試一般還有出一些場景題綜合考察面試者的水平,這類場景題一般是多種技術的結合,可以參考我這里寫的:《來看一看兩道大廠面試場景題》。