第四次的面试 C++ 面试 (迷茫) + (复习知识点)
1.請你說說 TCP 和 UDP 的區(qū)別
1.TCP是面向?qū)ο筮B接;而UDP是無面向?qū)ο筮B接
2.TCP確保所傳輸?shù)臄?shù)據(jù)一定會到達目的地,但時間卻不能保證;而UDP不確保數(shù)據(jù)會按原來順序到達,但具有實時性
3.TCP的使用場景是不在意傳輸數(shù)據(jù)速度,但在意傳輸數(shù)據(jù)準確;而UDP的使用場景則是對實時性要求較高
4.TCP的首部開銷大,占用20字節(jié);而UDP的首部開銷小,只占用8個字節(jié)
5.TCP只支持點對點的數(shù)據(jù)傳輸;而UDP支持一對一、一對多、多對多等各種場景
6.TCP有擁塞控制和流量控制來確保數(shù)據(jù)的安全性,但如果網(wǎng)絡擁塞的話,速度會比較慢;UDP即使在網(wǎng)絡擁塞的時候,傳輸速度也不會慢
2.請你說說 TCP 三次握手四次揮手過程
tcp的三次揮手:的作用是保證 通信雙方都能夠正常的收發(fā)信息;三次握手的發(fā)生階段是在客戶端連接服務器的connect階段開始的.
1.首先客戶端發(fā)送一個syn=1,ack給服務器,
2.服務器接收到之后將ack+1,syn=1,ACK包給客戶端
3.客戶端在將ACK+1,ack +1包發(fā)送給服務器,這樣服務器收到之后就能夠,服務器客戶端就能夠雙方都知道可以相互通信,三次握手完成可以開始傳輸數(shù)據(jù)。
tcp的四次揮手:的作用是將服務器和客戶端的連接安全的斷開,四次揮手是發(fā)生在客戶端或者服務器斷開連接的時候.
4.客戶端向服務器發(fā)送一個fin=1,ack包,
5.服務器收到之后將ack+1包發(fā)送給客戶端,
6.這時候,服務器會講傳輸?shù)臄?shù)據(jù)傳輸完,之后再發(fā)一個fin的包給客戶端,
7.客戶端收到之后發(fā)送一個ACK=1,ack+1包給服務器,這樣四次揮手就完成了,服務器和客戶端雙方都斷開了鏈接。
3.請你說說 GET 和 POST 的區(qū)別
GET方法是向服務器請求數(shù)據(jù)的,而POST方法是向服務器上傳數(shù)據(jù)的
1.最明顯的功能用途不同,GET用于查詢/獲取數(shù)據(jù),POST用于提交或修改數(shù)據(jù)
2.GET有長度限制(2048字節(jié)),POST沒有長度限制
3.GET的參數(shù)會附在url之后,以?分隔url和傳輸?shù)臄?shù)據(jù),而POST的內(nèi)容會放在請求體之中。 4.GET是明文傳輸,可以直接在url中看到信息,而POST傳輸?shù)臄?shù)據(jù)無法直接看到
5.GET請求會保存在瀏覽器歷史記錄中,會被瀏覽器主動緩存,而post不會,除非手動設置
6.GET請求的參數(shù)類型只接受ASCII字符,而Post沒有限制
7.get在瀏覽器回退時是無害的,而post會再次提交請求。
4.簡述一下 C++ 中的多態(tài)
C++中的多態(tài)分為兩種,靜態(tài)多態(tài)和動態(tài)多態(tài)。
靜態(tài)多態(tài)一般是在編譯時實現(xiàn),主要有函數(shù)重載,運算符重載和泛型編程。
動態(tài)多態(tài)一般是運行時實現(xiàn),主要有虛函數(shù)的實現(xiàn)
1.靜態(tài)多態(tài)有函數(shù)重載,運算符重載等,是在編譯階段就確認了函數(shù)地址,編譯器會根據(jù)實參類型來選擇調(diào)用合適的函數(shù);
2.動態(tài)多態(tài)在程序運行階段確認函數(shù)地址,通過派生類和虛函數(shù)實現(xiàn)運行時的多態(tài),
在運行時,通過基類指針或者引用指向的對象來確認應該調(diào)用哪個類的虛函數(shù),當父類指針(引用)指向的是父類,則調(diào)用父類函數(shù),當指向的是子類則調(diào)用子類的函數(shù).
3.實現(xiàn)動態(tài)多態(tài)的條件:要有繼承關系以及虛函數(shù)重寫(virtual),父類指針(引用)指向子類對象
4.動態(tài)多態(tài)實現(xiàn)原理:當類中聲明虛函數(shù)時,編譯器會在類中生成一個虛函數(shù)表,這個虛函數(shù)表由編譯器自己維護;存在虛函數(shù)時,每一個對象都有一個指向虛函數(shù)表的指針,多態(tài)條用時虛函數(shù)指針會根據(jù)這個對象對應類的虛函數(shù)找到被調(diào)用函數(shù)入口.
5.請你介紹一下死鎖,產(chǎn)生的必要條件,產(chǎn)生的原因,怎么預防死鎖
1.死鎖的概念以及產(chǎn)生條件:死鎖是兩個或兩個以上的進程之間由于競爭現(xiàn)象而導致進程都不能繼續(xù)執(zhí)行的現(xiàn)象。
2.產(chǎn)生死鎖的三個必要條件是互斥、不搶占和占有并等待,這些條件都具備只是有可能會造成死鎖,只有第四個條件循環(huán)等待也具備的時候才會必然出現(xiàn)死鎖。
3.如何避免:
破壞不可搶占條件(可以讓優(yōu)先級高的進程搶占優(yōu)先級低的進程的資源)、
破壞請求與保持條件(當進程申請不到自己所需要的的資源時,必須釋放掉自己所持有的資源)
破壞循環(huán)等待條件(進程只能往前申請資源,不能往后申請資源)
如何預防:有序資源分配法、銀行家算法.
6.請你說說 MySQL 索引,以及它們的好處和壞處
1.索引是對數(shù)據(jù)庫表中的一列或多列的值,進行排序的一種結(jié)構(gòu) ,使用索引可以快速訪問數(shù)據(jù)庫表中的特定信息,是加快數(shù)據(jù)庫查詢的技術。
2.索引好處:可以避免全表掃描,確保索引數(shù)據(jù)的唯一性,提升數(shù)據(jù)庫查詢性能。
3.索引壞處:創(chuàng)建和維護索引需要消耗時間,占用物理空間,當表中數(shù)據(jù)增加、刪除和修改時,索引需要動態(tài)維護,降低了數(shù)據(jù)的維護速度。
7.簡述一下什么是面向?qū)ο?/strong>
面向?qū)ο蟮娜笏枷?#xff1a;
1.封裝:將客觀事物進行抽象,將其屬性和方法合成為一個類,類封裝了成員變量和成員函數(shù),同時又實現(xiàn)對屬性和方法的權限控制,降低與外界的耦合度.
2.繼承:子類繼承父類的各種屬性和方法,同時子類還可以在父類的基礎上重新定義和擴展父類的屬性和方法,使其具有不同的功能,繼承提高了代碼的復用性及可維護性.
3.多態(tài):同一調(diào)用語句在父類和子類間使用時具有不同的表現(xiàn)形式,可以使用同一段代碼處理不同類型的對象,提高代碼的復用性.
8.說一說進程通信的方式有哪些?
1.管道
2.消息隊列
3.共享內(nèi)存
4.信號量
5.套接字
6.信號、
一個鏈接:
系統(tǒng)編程__She001的博客-CSDN博客
9.請你說說進程和線程的區(qū)別
?1. 進程有獨立的地址空間,線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間;
2. 進程和線程切換時,需要切換進程和線程的上下文,進程的上下文切換時間開銷遠遠大于線程上下文切換時間,耗費資源較大,效率要差一些;
3. 進程的并發(fā)性較低,線程的并發(fā)性較高;
4. 每個獨立的進程有一個程序運行的入口、順序執(zhí)行序列和程序的出口,但是線程不能夠獨立執(zhí)行,必須依存在應用程序中,由應用程序提供多個線程執(zhí)行控制;
5. 系統(tǒng)在運行的時候會為每個進程分配不同的內(nèi)存空間;而對線程而言,除了 CPU 外,系統(tǒng)不會為線程分配內(nèi)存(線程所使用的資源來自其所屬進程的資源),線程組之間只能共享資源;
6. 一個進程崩潰后,在保護模式下不會對其他進程產(chǎn)生影響,但是一個線程崩潰整個進程都死掉。所以多進程要比多線程健壯。
10.說一說 epoll 的原理
得分點 epoll_create、epoll_ctrl、epoll_wt、紅黑樹、雙向鏈表、epoll的兩種工作模式 標準回答 epoll 是一種更加高效的 IO 復用技術,epoll 的使用步驟及原理如下:?
1. 調(diào)用 epoll_create() 會在內(nèi)核中創(chuàng)建一個 eventpoll 結(jié)構(gòu)體數(shù)據(jù),稱之為 epoll 對象,在這個結(jié)構(gòu)體中有 2 個比較重要的數(shù)據(jù)成員,一個是需要檢測的文件描述符的信息 struct_root rbr(紅黑樹),還有一個是就緒列表struct list_head rdlist,存放檢測到數(shù)據(jù)發(fā)送改變的文件描述符信息(雙向鏈表);
?2. 調(diào)用 epoll_ctrl() 可以向 epoll 對象中添加、刪除、修改要監(jiān)聽的文件描述符及事件;?
3. 調(diào)用 epoll_wt() 可以讓內(nèi)核去檢測就緒的事件,并將就緒的事件放到就緒列表中并返回,通過返回的事件數(shù)組做進一步的事件處理。 epoll 的兩種工作模式:
?1. LT 模式(水平觸發(fā)) LT(Level - Triggered)是缺省的工作方式,并且同時支持 Block 和 Nonblock Socket。在這種做法中,內(nèi)核檢測到一個文件描述符就緒了,然后可以對這個就緒的 fd 進行 IO 操作,如果不作任何操作,內(nèi)核還是會繼續(xù)通知。?
2. ET 模式(邊沿觸發(fā)) ET(Edge - Triggered)是高速工作方式,只支持 Nonblock socket。在這種模式下,當描述符從未就緒變?yōu)榫途w時,內(nèi)核通過 epoll 檢測到。然后它會假設你知道文件描述符已經(jīng)就緒,并且不會再為那個文件描述符發(fā)送更多的就緒通知,直到你做了某些操作導致那個文件描述符不再為就緒狀態(tài)了。但是請注意,如果一直不對這個 fd 進行 IO 操作(從而導致它再次變成未就緒),內(nèi)核不會發(fā)送更多的通知(only once)。 ET 模式在很大程度上減少了 epoll 事件被重復觸發(fā)的次數(shù),因此效率要比 LT 模式高。epoll 工作在 ET 模式的時候,必須使用非阻塞套接口,以避免由于一個文件描述符的阻塞讀/阻塞寫操作把處理多個文件描述符的任務餓死。
11.瀏覽器從輸入 URL 開始到頁面顯示內(nèi)容,中間發(fā)生了什么?
1.輸入地址,瀏覽器查找域名的 IP 地址。
2.瀏覽器向 該 IP 地址的web 服務器發(fā)送一個 HTTP 請求,在發(fā)送請求之前瀏覽器和服務器建立TCP的三次握手,判斷是否是HTTP緩存,如果是強制緩存且在有效期內(nèi),不再向服務器發(fā)請求,如果是HTTP協(xié)商緩存向后端發(fā)送請求且和后端服務器對比,在有效期內(nèi),服務器返回304,直接從瀏覽器獲取數(shù)據(jù),如果不在有效期內(nèi)服務器返回200,返回新數(shù)據(jù)。
3.請求發(fā)送出去服務器返回重定向,瀏覽器再按照重定向的地址重新發(fā)送請求。
4.如果請求的參數(shù)有問題,服務器端返回404,如果服務器端掛了返回500。
5.如果有數(shù)據(jù)一切正常,當瀏覽器拿到服務器的數(shù)據(jù)之后,開始渲染頁面同時獲取HTML頁面中圖片、音頻、視頻、CSS、JS,在這期間獲取到JS文件之后,會直接執(zhí)行JS代碼,阻塞瀏覽器渲染,因為渲染引擎和JS引擎互斥,不能同時工作,所以通常把Script標簽放在body標簽的底部。
6.渲染過程就是先將HTML轉(zhuǎn)換成dom樹,再將CSS樣式轉(zhuǎn)換成stylesheet,根據(jù)dom樹和stylesheet創(chuàng)建布局樹,對布局樹進行分層,為每個圖層生成繪制列表,再將圖層分成圖塊,緊接著光柵化將圖塊轉(zhuǎn)換成位圖,最后合成繪制生成頁面。
12.請你說說 HTTP 狀態(tài)碼及其含義
?標準回答 HTTP狀態(tài)碼有:
1xx代表服務器端已經(jīng)接受了請求。
2xx代表請求已經(jīng)被服務器端成功接收,最常見的有200、201狀態(tài)碼。
3xx代表路徑被服務器端重定向到了一個新的URL,最常見的有301、302狀態(tài)碼。
4xx代表客戶端的請求發(fā)生了錯誤,最常見的有401、404狀態(tài)碼。
5xx代表服務器端的響應出現(xiàn)了錯誤。
加分回答 - 1xx:指定客戶端相應的某些動作,代表請求已被接受,需要繼續(xù)處理。由于 HTTP/1.0 協(xié)議中沒有定義任何 1xx 狀態(tài)碼,所以除非在某些試驗條件下,服務器禁止向此類客戶端發(fā)送 1xx 響應。 - 2xx:代表請求已成功被服務器接收、理解、并接受。這系列中最常見的有200、201狀態(tài)碼。 - 200(成功):服務器已成功處理了請求。 通常,這表示服務器提供了請求的網(wǎng)頁。 - 201(已創(chuàng)建):請求成功并且服務器創(chuàng)建了新的資源。 - 202(已接受):服務器已接受請求,但尚未處理。 - 203(非授權信息):服務器已成功處理了請求,但返回的信息可能來自另一來源。 - 204(無內(nèi)容):服務器成功處理了請求,但沒有返回任何內(nèi)容。 - 205(重置內(nèi)容):服務器成功處理了請求,但沒有返回任何內(nèi)容。 - 206(部分內(nèi)容):服務器成功處理了部分 GET 請求。 - 3xx:代表需要客戶端采取進一步的操作才能完成請求,這些狀態(tài)碼用來重定向,后續(xù)的請求地址(重定向目標)在響應頭Location字段中指明。這系列中最常見的有301、302狀態(tài)碼。 - 300(多種選擇):針對請求,服務器可執(zhí)行多種操作。 服務器可根據(jù)請求者 (user agent) 選擇一項操作,或提供操作列表供請求者選擇。 - 301(永久移動):請求的網(wǎng)頁已永久移動到新位置。 服務器返回此響應(對 GET 或 HEAD 請求的響應)時,會自動將請求者轉(zhuǎn)到新位置。 - 302(臨時移動):服務器目前從不同位置的網(wǎng)頁響應請求,但請求者應繼續(xù)使用原有位置來進行以后的請求。 - 303(查看其他位置):請求者應當對不同的位置使用單獨的 GET 請求來檢索響應時,服務器返回此代碼。 - 304(未修改):自從上次請求后,請求的網(wǎng)頁未修改過。 服務器返回此響應時,不會返回網(wǎng)頁內(nèi)容。 - 305(使用代理):請求者只能使用代理訪問請求的網(wǎng)頁。 如果服務器返回此響應,還表示請求者應使用代理。 - 307(臨時重定向):服務器目前從不同位置的網(wǎng)頁響應請求,但請求者應繼續(xù)使用原有位置來進行以后的請求。 - 4xx:表示請求錯誤。代表了客戶端看起來可能發(fā)生了錯誤,妨礙了服務器的處理。常見有:401、404狀態(tài)碼。 - 400(錯誤請求):服務器不理解請求的語法。 - 401(未授權):請求要求身份驗證。 對于需要登錄的網(wǎng)頁,服務器可能返回此響應。 - 403(禁止):服務器拒絕請求。 - 404(未找到):服務器找不到請求的網(wǎng)頁。 - 405(方法禁用):禁用請求中指定的方法。 - 406(不接受):無法使用請求的內(nèi)容特性響應請求的網(wǎng)頁。 - 407(需要代理授權):此狀態(tài)代碼與 401(未授權)類似,但指定請求者應當授權使用代理。 - 408(請求超時):服務器等候請求時發(fā)生超時。 - 409(沖突):服務器在完成請求時發(fā)生沖突。 服務器必須在響應中包含有關沖突的信息。 - 410(已刪除):如果請求的資源已永久刪除,服務器就會返回此響應。 - 411(需要有效長度):服務器不接受不含有效內(nèi)容長度標頭字段的請求。 - 412(未滿足前提條件):服務器未滿足請求者在請求中設置的其中一個前提條件。 - 413(請求實體過大):服務器無法處理請求,因為請求實體過大,超出服務器的處理能力。 - 414(請求的 URI 過長):請求的 URI(通常為網(wǎng)址)過長,服務器無法處理。 - 415(不支持的媒體類型):請求的格式不受請求頁面的支持。 - 416(請求范圍不符合要求):如果頁面無法提供請求的范圍,則服務器會返回此狀態(tài)代碼。 - 417 (未滿足期望值):服務器未滿足"期望"請求標頭字段的要求。 - 5xx:代表了服務器在處理請求的過程中有錯誤或者異常狀態(tài)發(fā)生,也有可能是服務器意識到以當前的軟硬件資源無法完成對請求的處理。常見有500、503狀態(tài)碼。 - 500(服務器內(nèi)部錯誤):服務器遇到錯誤,無法完成請求。 - 501(尚未實施):服務器不具備完成請求的功能。 例如,服務器無法識別請求方法時可能會返回此代碼。 - 502(錯誤網(wǎng)關):服務器作為網(wǎng)關或代理,從上游服務器收到無效響應。 - 503(服務不可用):服務器目前無法使用(由于超載或停機維護)。 通常,這只是暫時狀態(tài)。 - 504(網(wǎng)關超時):服務器作為網(wǎng)關或代理,但是沒有及時從上游服務器收到請求。 - 505(HTTP 版本不受支持):服務器不支持請求中所用的 HTTP 協(xié)議版本。
?13.說一說常用的 Linux 命令
常用的 Linux 命令有:
1.? cd:切換當前目錄
2.? ls:查看當前文件與目錄
3.? grep:通常與管道命令一起使用,用于對一些命令的輸出進行篩選加工
4.? cp:復制文件或文件夾
5.? mv:移動文件或文件夾
6.? rm:刪除文件或文件夾
7.? ps:查看進程情況
8.? kill:向進程發(fā)送信號
9.? tar:對文件進行打包
10.? cat:查看文件內(nèi)容
11.? top:查看操作系統(tǒng)的信息,如進程、CPU占用率、內(nèi)存信息等(實時)
12.? free:查看內(nèi)存使用情況
13.? pwd:顯示當前工作目錄
14.請你說說 HTTP 和 HTTPS 的區(qū)別
1.由于HTTP簡單快速的特性,當客戶端向服務器端請求數(shù)據(jù)的時候,只需要傳送請求方法和路徑就可以取到結(jié)果,基于TCP,默認端口號為80,耗時可以簡略計算為1RTT,傳遞的數(shù)據(jù)全部是明文傳輸,幾乎沒有安全性。 HTTPS是基于TLS的,而TLS又基于TCP,當客戶端向服務器端請求數(shù)據(jù)的時候,服務器大概率會將客戶端重定向到該服務器的443端口,進行新的TCP連接,此時服務器會返回一個證書文件,而不是響應報文體。此時客戶端驗證證書文件緊接創(chuàng)建對稱密鑰,之后重新和服務器建立TLS連接,當服務器返回ACK確認之后,連接正式建立,此時上方整個過程耗時為3RTT,并且之后和服務器的通信數(shù)據(jù)都是通過對稱密鑰加密過的,幾乎無法破解。
HTTP和HTTPS的不同點總結(jié)如下:?
1.? ?HTTP是基于TCP的,而HTTPS是基于TLS的 - HTTP的往返時間為1RTT,而HTTPS的往返時間為3RTT
2.? ?HTTP只需要創(chuàng)建一次TCP連接,而HTTPS需要創(chuàng)建兩次TCP連接
3.? HTTP的默認端口號為80,而HTTPS的默認端口號為443
4.? ?HTTP的安全性很差,而HTTPS的安全性很強 。加分回答 HTTPS雖然在安全方面有很大的優(yōu)勢,但是缺點也很明顯,如下: - HTTPS握手階段耗費時間,幾乎是HTTP的數(shù)倍,會延長頁面的首次繪制時間和增加耗電 - HTTPS的效率沒有HTTP高,如果部分數(shù)據(jù)內(nèi)容實際上并不需要加密,會平白浪費計算機資源 - HTTPS的證書需要購買,功能越強大的證書價格更高 - HTTPS的加密并不能阻止某些網(wǎng)絡攻擊,如黑客攻擊、拒絕服務攻擊等。
15.簡述一下淺拷貝和深拷貝? (類里面的構(gòu)造函數(shù))
1. 淺拷貝 淺拷貝又稱為值拷貝,將源對象的值拷貝到目標對象中,如果對象中有某個成員是指針類型數(shù)據(jù),并且是在堆區(qū)創(chuàng)建,則使用淺拷貝僅僅拷貝的是這個指針變量的值,也就是在目標對象中該指針類型數(shù)據(jù)和源對象中的該成員指向的是同一塊堆空間。這樣會帶來一個問題,就是在析構(gòu)函數(shù)中釋放該堆區(qū)數(shù)據(jù),會被釋放多次。默認的拷貝構(gòu)造函數(shù)和默認的賦值運算符重載函數(shù)都是淺拷貝。
?2. 深拷貝 深拷貝在拷貝的時候先開辟出和源對象大小一樣的空間,然后將源對象里的內(nèi)容拷貝到目標對象中去,這樣指針成員就指向了不同的內(nèi)存位置。并且里面的內(nèi)容是一樣的,這樣不但達到了拷貝的目的,還不會出現(xiàn)問題,兩個對象先后去調(diào)用析構(gòu)函數(shù),分別釋放自己指針成員所指向的內(nèi)存。即為每次增加一個指針,便申請一塊新的內(nèi)存,并讓這個指針指向新的內(nèi)存,深拷貝情況下,不會出現(xiàn)重復釋放同一塊內(nèi)存的錯誤。
16.請你說說三種智能指針實現(xiàn)原理和使用場景,以及其線程安全
?1. 智能指針實現(xiàn)原理 建立所有權(ownership)概念,對于特定的對象,只能有一個智能指針可擁有它,這樣只有擁有對象的智能指針的析構(gòu)函數(shù)會刪除該對象。然后,讓賦值操作轉(zhuǎn)讓所有權。這就是用于 auto_ptr 和 unique_ptr 的策略,但 unique_ptr 的策略更嚴格,unique_ptr 能夠在編譯期識別錯誤。 跟蹤引用特定對象的智能指針計數(shù),這稱為引用計數(shù)(reference counting)。例如,賦值時,計數(shù)將加 1,而指針過期時,計數(shù)將減 1. 僅當最后一個指針過期時,才調(diào)用 delete。這是 shared_ptr 采用的策略。
?2. 使用場景 如果程序要使用多個指向同一個對象的指針,應該選擇 shared_ptr; 如果程序不需要多個指向同一個對象的指針,則可以使用 unique_ptr; 如果使用 new [] 分配內(nèi)存,應該選擇 unique_ptr; 如果函數(shù)使用 new 分配內(nèi)存,并返回指向該內(nèi)存的指針,將其返回類型聲明為 unique_ptr 是不錯的選擇。
?3. 線程安全 shared_ptr 智能指針的引用計數(shù)在手段上使用了 atomic 原子操作,只要 shared_ptr 在拷貝或賦值時增加引用,析構(gòu)時減少引用就可以了。首先原子是線程安全的,所有 shared_ptr 智能指針在多線程下引用計數(shù)也是安全的,也就是說 shared_ptr 智能指針在多線程下傳遞使用時引用計數(shù)是不會有線程安全問題的。 但是指向?qū)ο蟮闹羔槻皇蔷€程安全的,使用 shared_ptr 智能指針訪問資源不是線程安全的,需要手動加鎖解鎖。智能指針的拷貝也不是線程安全的。
17.請你說說 TCP 如何實現(xiàn)可靠傳輸? ?和UDP 怎么樣可以實現(xiàn)可靠的傳輸?
TCP部分
可靠傳輸就是通過TCP連接傳送的數(shù)據(jù)是沒有差錯、不會丟失、不重復并且按序到達的。TCP是通過序列號、檢驗和、確認應答信號、重發(fā)機制、連接管理、窗口控制、流量控制、擁塞控制一起保證TCP傳輸?shù)目煽啃缘摹?/p>
可靠傳輸?shù)木唧w實現(xiàn)是:
1.應用層的數(shù)據(jù)會被分割成TCP認為最適合發(fā)送的數(shù)據(jù)塊。
2.序列號:TCP給發(fā)送的每一個包都進行編號,接收方對數(shù)據(jù)包進行排序,把有序數(shù)據(jù)傳送給應用層,TCP的接收端會丟棄重復的數(shù)據(jù)。
3. 檢驗和:TCP將保持它首部和數(shù)據(jù)的檢驗和。這是一個端到端的檢驗和,目的是檢測數(shù)據(jù)在傳輸過程中的任何變化。
4.確認應答:如果收到的數(shù)據(jù)報報文段的檢驗和沒有差錯,就確認收到,如果有差錯,TCP就丟棄這個報文段和不確認收到此報文段。
5. 流量控制:TCP 連接的每一方都有固定大小的緩沖空間,TCP的接收端只允許發(fā)送端發(fā)送接收端緩沖區(qū)能接納的數(shù)據(jù)。當接收方來不及處理發(fā)送方的數(shù)據(jù),能提示發(fā)送方降低發(fā)送的速率,防止包丟失。TCP 使用的流量控制協(xié)議是可變大小的滑動窗口協(xié)議。
6.擁塞控制:當網(wǎng)絡擁塞時,減少數(shù)據(jù)的發(fā)送。
7. 停止等待協(xié)議:它的基本原理就是每發(fā)完一個分組就停止發(fā)送,等待對方確認。在收到確認后再發(fā)下一個分組。
8.超時重傳: 當 TCP 發(fā)出一個段后,它啟動一個定時器,等待目的端確認收到這個報文段。如果不能及時收到一個確認,將重發(fā)這個報文段。
UDP 部分
UDP不是面向連接的協(xié)議,因此資源消耗小,處理速度快的優(yōu)點,所以通常音頻、視頻和普通數(shù)據(jù)在傳送時使用UDP較多,因為它們即使偶爾丟失一兩個數(shù)據(jù)包,也不會對接收結(jié)果產(chǎn)生太大影響。如果想要使用UDP還要保證數(shù)據(jù)的可靠傳輸,就只能通過應用層來做文章。實現(xiàn)的方式可以參考TCP的可靠傳輸機制,差別就是將TCP傳輸層功能,如確認機制、重傳功能、流量控制、擁塞控制等功能實現(xiàn)在了應用層。 加分回答 在應用層實現(xiàn)可靠傳輸關鍵點有兩個,從應用層角度考慮分別是:
?1. 提供超時重傳機制,能避免數(shù)據(jù)報丟失的問題。?
2. 提供確認序列號,保證數(shù)據(jù)拼接時候的正確排序。 請求端:首先在UDP數(shù)據(jù)報定義一個首部,首部包含確認序列號和時間戳,時間戳是用來計算RTT(數(shù)據(jù)報傳輸?shù)耐禃r間),計算出合適的RTO(重傳的超時時間)。然后以等-停的方式發(fā)送數(shù)據(jù)報,即收到對端的確認之后才發(fā)送下一個的數(shù)據(jù)報。當時間超時,本端重傳數(shù)據(jù)報,同時RTO擴大為原來的兩倍,重新開始計時。 響應端:接受到一個數(shù)據(jù)報之后取下該數(shù)據(jù)報首部的時間戳和確認序列號,并添加本端的確認數(shù)據(jù)報首部之后發(fā)送給對端。根據(jù)此序列號對已收到的數(shù)據(jù)報進行排序并丟棄重復的數(shù)據(jù)報。
18.請你介紹一下數(shù)據(jù)庫的 ACID (這是啥,沒有聽過)
?事務可由一條非常簡單的SQL語句組成,也可以由一組復雜的SQL語句組成。在事務中的操作,要么都執(zhí)行修改,要么都不執(zhí)行,這就是事務的目的,也是事務模型區(qū)別于文件系統(tǒng)的重要特征之一。 事務需遵循ACID四個特性:
?1.? ??A(atomicity),原子性。原子性指整個數(shù)據(jù)庫事務是不可分割的工作單位。只有使事務中所有的數(shù)據(jù)庫操作都執(zhí)行成功,整個事務的執(zhí)行才算成功。事務中任何一個SQL語句執(zhí)行失敗,那么已經(jīng)執(zhí)行成功的SQL語句也必須撤銷,數(shù)據(jù)庫狀態(tài)應該退回到執(zhí)行事務前的狀態(tài)。
2.? ???C(consistency),一致性。一致性指事務將數(shù)據(jù)庫從一種狀態(tài)轉(zhuǎn)變?yōu)榱硪环N一致的狀態(tài)。在事務開始之前和事務結(jié)束以后,數(shù)據(jù)庫的完整性約束沒有被破壞。
3.? ? I(isolation),隔離性。事務的隔離性要求每個讀寫事務的對象與其他事務的操作對象能相互分離,即該事務提交前對其他事務都不可見,這通常使用鎖來實現(xiàn)。 -
4.? ?D(durability) ,持久性。事務一旦提交,其結(jié)果就是永久性的,即使發(fā)生宕機等故障,數(shù)據(jù)庫也能將數(shù)據(jù)恢復。持久性保證的是事務系統(tǒng)的高可靠性,而不是高可用性。 加分回答 事務可以分為以下幾種類型:
- 扁平事務:是事務類型中最簡單的一種,而在實際生產(chǎn)環(huán)境中,這可能是使用最為頻繁的事務。在扁平事務中,所有操作都處于同一層次,其由BEGIN WORK開始,由COMMIT WORK或ROLLBACK WORK結(jié)束。處于之間的操作是原子的,要么都執(zhí)行,要么都回滾。
- 帶有保存點的扁平事務:除了支持扁平事務支持的操作外,允許在事務執(zhí)行過程中回滾到同一事務中較早的一個狀態(tài),這是因為可能某些事務在執(zhí)行過程中出現(xiàn)的錯誤并不會對所有的操作都無效,放棄整個事務不合乎要求,開銷也太大。保存點(savepoint)用來通知系統(tǒng)應該記住事務當前的狀態(tài),以便以后發(fā)生錯誤時,事務能回到該狀態(tài)。
- 鏈事務:可視為保存點模式的一個變種。鏈事務的思想是:在提交一個事務時,釋放不需要的數(shù)據(jù)對象,將必要的處理上下文隱式地傳給下一個要開始的事務。注意,提交事務操作和開始下一個事務操作將合并為一個原子操作。這意味著下一個事務將看到上一個事務的結(jié)果,就好像在一個事務中進行的。
- 嵌套事務:是一個層次結(jié)構(gòu)框架。有一個頂層事務(top-level transaction)控制著各個層次的事務。頂層事務之下嵌套的事務被稱為子事務(subtransaction),其控制每一個局部的變換。
- 分布式事務:通常是一個在分布式環(huán)境下運行的扁平事務,因此需要根據(jù)數(shù)據(jù)所在位置訪問網(wǎng)絡中的不同節(jié)點。對于分布式事務,同樣需要滿足ACID特性,要么都發(fā)生,要么都失效。 對于MySQL的InnoDB存儲引擎來說,它支持扁平事務、帶有保存點的扁平事務、鏈事務、分布式事務。對于嵌套事務,MySQL數(shù)據(jù)庫并不是原生的,因此對于有并行事務需求的用戶來說MySQL就無能為力了,但是用戶可以通過帶有保存點的事務來模擬串行的嵌套事務。
19.請你說說 C++11、C++14、C++17、?都有什么新特性
1. C++11 新特新 - static_assert 編譯時斷言 - 新增加類型 long long ,unsigned long long,char16_t,char32_t,原始字符串 - auto - decltype - 委托構(gòu)造函數(shù) - constexpr - 模板別名 - alignas - alignof - 原子操作庫 - nullptr - 顯示轉(zhuǎn)換運算符 - 繼承構(gòu)造函數(shù) - 變參數(shù)模板 - 列表初始化 - 右值引用 - Lambda 表達式 - override、final - unique_ptr、shared_ptr - initializer_list - array、unordered_map、unordered_set - 線程支持庫
2. C++14 新特新 - 二進制字面量 - 泛型 Lambda 表達式 - 帶初始化/泛化的 Lambda 捕獲 - 變量模板 - [[deprecated]]屬性 - std::make_unique - std::shared_timed_mutex、std::shared_lock - std::quoted - std::integer_sequence - std::exchange
3. C++17 新特新 - 構(gòu)造函數(shù)模板推導 - 結(jié)構(gòu)化綁定 - 內(nèi)聯(lián)變量 - 折疊表達式 - 字符串轉(zhuǎn)換 - std::shared_mutex 4. C++20 新特新 - 允許 Lambda 捕獲 [=, this] - 三路比較運算符 - char8_t - 立即函數(shù)(consteval) - 協(xié)程 - constinit
20.說一說進程有多少種狀態(tài),如何轉(zhuǎn)換
1. 進程有五種狀態(tài):創(chuàng)建、就緒、執(zhí)行、阻塞、終止:
- 創(chuàng)建:一個進程啟動,首先進入創(chuàng)建狀態(tài),需要獲取系統(tǒng)資源創(chuàng)建進程管理塊(PCB:Process Control Block)完成資源分配。
- 就緒狀態(tài):在創(chuàng)建狀態(tài)完成之后,進程已經(jīng)準備好,處于就緒狀態(tài),但是還未獲得處理器資源,無法運行。
- 運行狀態(tài):獲取處理器資源,被系統(tǒng)調(diào)度,當具有時間片開始進入運行狀態(tài)。如果進程的時間片用完了就進入就緒狀態(tài)。
- 阻塞狀態(tài):在運行狀態(tài)期間,如果進行了阻塞的操作,此時進程暫時無法操作就進入到了阻塞狀態(tài),在這些操作完成后就進入就緒狀態(tài)。等待再次獲取處理器資源,被系統(tǒng)調(diào)度,當具有時間片就進入運行狀態(tài)。
- 終止狀態(tài):進程結(jié)束或者被系統(tǒng)終止,進入終止狀態(tài)。
?21.說一說 select 的原理以及缺點
?select 是 一種 IO 多路復用技術,它的主旨思想是:
1. 首先要構(gòu)造一個關于文件描述符的列表,將要監(jiān)聽的文件描述符添加到該列表中,這個文件描述符的列表數(shù)據(jù)類型為 fd_set,它是一個整型數(shù)組,總共是 1024 個比特位,每一個比特位代表一個文件描述符的狀態(tài)。比如當需要 select 檢測時,這一位為 0 就表示不檢測對應的文件描述符的事件,為 1 表示檢測對應的文件描述符的事件。
2. 調(diào)用 select() 系統(tǒng)調(diào)用,監(jiān)聽該列表中的文件描述符的事件,這個函數(shù)是阻塞的,直到這些描述符中的一個或者多個進行 I/O 操作時,該函數(shù)才返回,并修改文件描述符的列表中對應的值,0 表示沒有檢測到該事件,1 表示檢測到該事件。函數(shù)對文件描述符的檢測的操作是由內(nèi)核完成的。
3. select() 返回時,會告訴進程有多少描述符要進行 I/O 操作,接下來遍歷文件描述符的列表進行 I/O 操作。
select 的缺點:
1. 每次調(diào)用select,都需要把 fd 集合從用戶態(tài)拷貝到內(nèi)核態(tài),這個開銷在 fd 很多時會很大;
2. 同時每次調(diào)用 select 都需要在內(nèi)核遍歷傳遞進來的所有 fd,這個開銷在 fd 很多時也很大;
3. select 支持的文件描述符數(shù)量太小了,默認是 1024(由 fd_set 決定);
4. 文件描述符集合不能重用,因為內(nèi)核每次檢測到事件都會修改,所以每次都需要重置;
5. 每次 select 返回后,只能知道有幾個 fd 發(fā)生了事件,但是具體哪幾個還需要遍歷文件描述符集合進一步判斷。
22.請你介紹一下 I/O 多路復用
?I/O 多路復用是一種使得程序能同時監(jiān)聽多個文件描述符的技術,從而提高程序的性能。I/O 多路復用能夠在單個線程中,通過監(jiān)視多個 I/O 流的狀態(tài)來同時管理多個 I/O 流,一旦檢測到某個文件描述符上我們關心的事件發(fā)生(就緒),能夠通知程序進行相應的處理(讀寫操作)。
Linux 下實現(xiàn) I/O 復用的系統(tǒng)調(diào)用主要有 select、poll 和 epoll。
1. select 的主旨思想: - 首先要構(gòu)造一個關于文件描述符的列表,將要監(jiān)聽的文件描述符添加到該列表中,這個文件描述符的列表數(shù)據(jù)類型為 fd_set,它是一個整型數(shù)組,總共是 1024 個比特位,每一個比特位代表一個文件描述符的狀態(tài)。比如當需要 select 檢測時,這一位為 0 就表示不檢測對應的文件描述符的事件,為 1 表示檢測對應的文件描述符的事件。 - 調(diào)用 select() 系統(tǒng)調(diào)用,監(jiān)聽該列表中的文件描述符的事件,這個函數(shù)是阻塞的,直到這些描述符中的一個或者多個進行 I/O 操作時,該函數(shù)才返回,并修改文件描述符的列表中對應的值,0 表示沒有檢測到該事件,1 表示檢測到該事件。函數(shù)對文件描述符的檢測的操作是由內(nèi)核完成的。 - select() 返回時,會告訴進程有多少描述符要進行 I/O 操作,接下來遍歷文件描述符的列表進行 I/O 操作。
select 的缺點:?
1. 每次調(diào)用select,都需要把 fd 集合從用戶態(tài)拷貝到內(nèi)核態(tài),這個開銷在 fd 很多時會很大;?
2. 同時每次調(diào)用 select 都需要在內(nèi)核遍歷傳遞進來的所有 fd,這個開銷在 fd 很多時也很大
3. select 支持的文件描述符數(shù)量太小了,默認是 1024(由 fd_set 決定);?
4. 文件描述符集合不能重用,因為內(nèi)核每次檢測到事件都會修改,所以每次都需要重置;?
5. 每次 select 返回后,只能知道有幾個 fd 發(fā)生了事件,但是具體哪幾個還需要遍歷文件描述符集合進一步判斷。
?2. poll poll 的原理和 select 類似,poll 支持的文件描述符沒有限制。
?3. epoll 是一種更加高效的 IO 復用技術,epoll 的使用步驟及原理如下: - 調(diào)用 epoll_create() 會在內(nèi)核中創(chuàng)建一個 eventpoll 結(jié)構(gòu)體數(shù)據(jù),稱之為 epoll 對象,在這個結(jié)構(gòu)體中有 2 個比較重要的數(shù)據(jù)成員,一個是需要檢測的文件描述符的信息 struct_root rbr(紅黑樹),還有一個是就緒列表struct list_head rdlist,存放檢測到數(shù)據(jù)發(fā)送改變的文件描述符信息(雙向鏈表); - 調(diào)用 epoll_ctrl() 可以向 epoll 對象中添加、刪除、修改要監(jiān)聽的文件描述符及事件; - 調(diào)用 epoll_wt() 可以讓內(nèi)核去檢測就緒的事件,并將就緒的事件放到就緒列表中并返回,通過返回的事件數(shù)組做進一步的事件處理。 epoll 的兩種工作模式: - LT 模式(水平觸發(fā)) LT(Level - Triggered)是缺省的工作方式,并且同時支持 Block 和 Nonblock Socket。在這種做法中,內(nèi)核檢測到一個文件描述符就緒了,然后可以對這個就緒的 fd 進行 IO 操作,如果不作任何操作,內(nèi)核還是會繼續(xù)通知。 - ET 模式(邊沿觸發(fā)) ET(Edge - Triggered)是高速工作方式,只支持 Nonblock socket。在這種模式下,當描述符從未就緒變?yōu)榫途w時,內(nèi)核通過 epoll 檢測到。然后它會假設你知道文件描述符已經(jīng)就緒,并且不會再為那個文件描述符發(fā)送更多的就緒通知,直到你做了某些操作導致那個文件描述符不再為就緒狀態(tài)了。但是請注意,如果一直不對這個 fd 進行 IO 操作(從而導致它再次變成未就緒),內(nèi)核不會發(fā)送更多的通知(only once)。 ET 模式在很大程度上減少了 epoll 事件被重復觸發(fā)的次數(shù),因此效率要比 LT 模式高。epoll 工作在 ET 模式的時候,必須使用非阻塞套接口,以避免由于一個文件描述符的阻塞讀/阻塞寫操作把處理多個文件描述符的任務餓死。
23.請你說說 new 的實現(xiàn)原理,new 和 malloc 的區(qū)別
?1. new 的實現(xiàn)原理: 如果是簡單類型,則直接調(diào)用 operator new(),在 operator new() 函數(shù)中會調(diào)用 malloc() 函數(shù),如果調(diào)用 malloc() 失敗會調(diào)用 _callnewh(),如果 _callnewh() 返回 0 則拋出 bac_alloc 異常,返回非零則繼續(xù)分配內(nèi)存。 如果是復雜類型,先調(diào)用 operator new()函數(shù),然后在分配的內(nèi)存上調(diào)用構(gòu)造函數(shù)。
2. new 和 malloc 的區(qū)別 - new 是操作符,而 malloc 是函數(shù);
?3. 使用 new 操作符申請內(nèi)存分配時無須指定內(nèi)存塊的大小,編譯器會根據(jù)類型信息自行計算,而 malloc 則需要顯式地指出所需內(nèi)存的尺寸;
4.? new 分配失敗的時候會直接拋出異常,malloc 分配失敗會返回 NULL;
?5. 對于非簡單類型,new 在分配內(nèi)存后,會調(diào)用構(gòu)造函數(shù),而 malloc 不會;
6. new 分配成功后會返回對應類型的指針,而 malloc 分配成功后會返回 void * 類型;
?7. malloc 可以分配任意字節(jié),new 只能分配實例所占內(nèi)存的整數(shù)倍數(shù)大小;
?8. new 可以被重載,而 malloc 不能被重載;
?9. new 操作符從自由存儲區(qū)上分配內(nèi)存空間,而 malloc 從堆上動態(tài)分配內(nèi)存;
?10. 使用 malloc 分配的內(nèi)存后,如果在使用過程中發(fā)現(xiàn)內(nèi)存不足,可以使用 realloc 函數(shù)進行內(nèi)存重新分配實現(xiàn)內(nèi)存的擴充,new 沒有這樣直觀的配套設施來擴充內(nèi)存。
24.說一說 STL 中有哪些常見的容器
?STL 中容器分為順序容器、關聯(lián)式容器、容器適配器三種類型,
三種類型容器特性分別如下: 1. 順序容器 容器并非排序的,元素的插入位置同元素的值無關,包含 vector、deque、list。
- vector:動態(tài)數(shù)組 元素在內(nèi)存連續(xù)存放。隨機存取任何元素都能在常數(shù)時間完成。在尾端增刪元素具有較佳的性能。
- deque:雙向隊列 元素在內(nèi)存連續(xù)存放。隨機存取任何元素都能在常數(shù)時間完成(僅次于 vector )。在兩端增刪元素具有較佳的性能(大部分情況下是常數(shù)時間)。
- list:雙向鏈表 元素在內(nèi)存不連續(xù)存放。在任何位置增刪元素都能在常數(shù)時間完成。不支持隨機存取。
2. 關聯(lián)式容器 元素是排序的;插入任何元素,都按相應的排序規(guī)則來確定其位置;在查找時具有非常好的性能;通常以平衡二叉樹的方式實現(xiàn),包含set、multiset、map、multimap
?- set/multiset set中不允許相同元素,multiset 中允許存在相同元素。
- map/multimap map 與 set 的不同在于 map 中存放的元素有且僅有兩個成員變,一個名為 first,另一個名為 second,map 根據(jù) first 值對元素從小到大排序,并可快速地根據(jù) first 來檢索元素。map 和multimap 的不同在于是否允許相同 first 值的元素。
3. 容器適配器 封裝了一些基本的容器,使之具備了新的函數(shù)功能,包含 stack,queue,priority_queue。
- stack:棧 棧是項的有限序列,并滿足序列中被刪除、檢索和修改的項只能是最進插入序列的項(棧頂?shù)捻?#xff09;,后進先出
?- queue:隊列 插入只可以在尾部進行,刪除、檢索和修改只允許從頭部進行,先進先出。
- priority_queue:優(yōu)先級隊列 內(nèi)部維持某種有序,然后確保優(yōu)先級最高的元素總是位于頭部,最高優(yōu)先級元素總是第一個出列。
25.STL 容器用過哪些,查找的時間復雜度是多少,為什么?
STL 中常用的容器有 vector、deque、list、map、set、multimap、multiset、unordered_map、unordered_set 等。容器底層實現(xiàn)方式及時間復雜度分別如下:
?1. vector 采用一維數(shù)組實現(xiàn),元素在內(nèi)存連續(xù)存放,不同操作的時間復雜度為: 插入: O(N) 查看: O(1) 刪除: O(N)
2. deque 采用雙向隊列實現(xiàn),元素在內(nèi)存連續(xù)存放,不同操作的時間復雜度為: 插入: O(N) 查看: O(1) 刪除: O(N)
3. list 采用雙向鏈表實現(xiàn),元素存放在堆中,不同操作的時間復雜度為: 插入: O(1) 查看: O(N) 刪除: O(1)
4. map、set、multimap、multiset 上述四種容器采用紅黑樹實現(xiàn),紅黑樹是平衡二叉樹的一種。不同操作的時間復雜度近似為: 插入: O(logN) 查看: O(logN) 刪除: O(logN)
5. unordered_map、unordered_set、unordered_multimap、 unordered_multiset 上述四種容器采用哈希表實現(xiàn),不同操作的時間復雜度為: 插入: O(1),最壞情況O(N) 查看: O(1),最壞情況O(N) 刪除: O(1),最壞情況O(N) 注意:容器的時間復雜度取決于其底層實現(xiàn)方式。
26.請你說說線程和協(xié)程的區(qū)別
?線程和協(xié)程的區(qū)別如下:
?1. 線程是操作系統(tǒng)的資源,線程的創(chuàng)建、切換、停止等都非常消耗資源,而創(chuàng)建協(xié)程不需要調(diào)用操作系統(tǒng)的功能,編程語言自身就能完成,所以協(xié)程也被稱為用戶態(tài)線程,協(xié)程比線程輕量很多;
?2. 線程在多核環(huán)境下是能做到真正意義上的并行,而協(xié)程是為并發(fā)而產(chǎn)生的;
?3. 一個具有多個線程的程序可以同時運行幾個線程,而協(xié)同程序卻需要彼此協(xié)作的運行;
?4. 線程進程都是同步機制,而協(xié)程則是異步;
?5. 線程是搶占式,而協(xié)程是非搶占式的,所以需要用戶自己釋放使用權來切換到其他協(xié)程,因此同一時間其實只有一個協(xié)程擁有運行權,相當于單線程的能力;
?6. 操作系統(tǒng)對于線程開辟數(shù)量限制在千的級別,而協(xié)程可以達到上萬的級別。
27.請你說說指針和引用的區(qū)別
指針和引用的區(qū)別有:
1. 定義和性質(zhì)不同。指針是一種數(shù)據(jù)類型,用于保存地址類型的數(shù)據(jù),而引用可以看成是變量的別名。指針定義格式為:數(shù)據(jù)類型 *;而引用的定義格式為:數(shù)據(jù)類型 &;
2. 引用不可以為空,當被創(chuàng)建的時候必須初始化,而指針變量可以是空值,在任何時候初始化;
3. 指針可以有多級,但引用只能是一級;
4. 引用使用時無需解引用(*),指針需要解引用;
5. 指針變量的值可以是 NULL,而引用的值不可以為 NULL;
6. 指針的值在初始化后可以改變,即指向其它的存儲單元,而引用在進行初始化后就不會再改變了;
7. sizeof 引用得到的是所指向的變量(對象)的大小,而 sizeof 指針得到的是指針變量本身的大小;
8. 指針作為函數(shù)參數(shù)傳遞時傳遞的是指針變量的值,而引用作為函數(shù)參數(shù)傳遞時傳遞的是實參本身,而不是拷貝副本;
9. 指針和引用進行++運算意義不一樣。
28.請你說說單例設計模式
1. 概念 單例設計模式(Singleton Pattern)是一種比較簡單的設計模式。這種類型的設計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式。這種模式涉及到一個單一的類,該類負責創(chuàng)建自己的對象,同時確保只有單個對象被創(chuàng)建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。注意: - 單例類只能有一個實例。 - 單例類必須自己創(chuàng)建自己的唯一實例。 - 單例類必須給所有其他對象提供這一實例。
?2. 單例設計模式的優(yōu)缺點 優(yōu)點: - 單例模式可以保證內(nèi)存里只有一個實例,減少了內(nèi)存的開銷。 - 可以避免對資源的多重占用。 - 單例模式設置全局訪問點,可以優(yōu)化和共享資源的訪問。 缺點: - 單例模式一般沒有接口,擴展困難。如果要擴展,則除了修改原來的代碼,沒有第二種途徑,違背開閉原則。 - 在并發(fā)測試中,單例模式不利于代碼調(diào)試。在調(diào)試過程中,如果單例中的代碼沒有執(zhí)行完,也不能模擬生成一個新的對象。 - 單例模式的功能代碼通常寫在一個類中,如果功能設計不合理,則很容易違背單一職責原則。?
3. C++ 單例設計模式的實現(xiàn) - 私有化構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、賦值函數(shù) - 定義一個私有的本類的靜態(tài)對象成員 - 定義一個公共的訪問該示例靜態(tài)成員方法,返回該靜態(tài)對象成員
4. 單例設計模式的種類 - 懶漢式:獲取該類的對象時才創(chuàng)建該類的實例 - 餓漢式:獲取該類的對象之前已經(jīng)創(chuàng)建好該類的實例
29.請你說說重載,重寫,隱藏的區(qū)別
重載、重寫、隱藏在定義、作用域、有無 virtual、函數(shù)名、形參列表、返回值類型等方面有區(qū)別。
1. 重載:在同一作用域中,同名函數(shù)的形式參數(shù)(參數(shù)個數(shù)、類型或者順序)不同時,構(gòu)成函數(shù)重載,與返回值類型無關。
2. 重寫:指不同作用域中定義的同名函數(shù)構(gòu)成隱藏(不要求函數(shù)返回值和函數(shù)參數(shù)類型相同)。比如派生類成員函數(shù)隱藏與其同名的基類成員函數(shù)、類成員函數(shù)隱藏全局外部函數(shù)。
隱藏的實質(zhì)是:在函數(shù)查找時,名字查找先于類型檢查。如果派生類中成員和基類中的成員同名,就隱藏掉。編譯器首先在相應作用域中查找函數(shù),如果找到名字一樣的則停止查找。
3. 派生類中與基類同返回值類型、同名和同參數(shù)的虛函數(shù)重定義,構(gòu)成虛函數(shù)覆蓋,也叫虛函數(shù)重寫。
30.請你說說 TCP 和 UDP 的使用場景
UDP:語音、視頻、尋址、游戲、廣播。
TCP:郵件、遠程登陸、超文本、文件、身份信息、重要內(nèi)容?
UDP的優(yōu)點是快,沒有TCP各種機制,少了很多首部信息和重復確認的過程,節(jié)省了大量的網(wǎng)絡資源。缺點是不可靠不穩(wěn)定,只管數(shù)據(jù)的發(fā)送不管過程和結(jié)果,網(wǎng)絡不好的時候很容易造成數(shù)據(jù)丟失。又因為網(wǎng)絡不好的時候不會影響到主機數(shù)據(jù)報的發(fā)送速率,這對很多實時的應用程序很重要,因為像語音通話、視頻會議等要求源主機要以恒定的速率發(fā)送數(shù)據(jù)報,允許網(wǎng)絡不好的時候丟失一些數(shù)據(jù),但不允許太大的延遲。DNS和ARP協(xié)議也是基于UDP實現(xiàn)的,要求快速獲取IP、MAC地址,如果基于TCP那么對整個因特網(wǎng)的資源占用過大且速度慢。還有游戲應用程序也是通過UDP來傳輸報文段,允許出現(xiàn)丟幀導致的卡頓,但是對游戲的整體體驗不會產(chǎn)生嚴重的影響。所以UDP在語音、視頻、尋址、游戲、廣播方面有很好的應用前景,實時性高,允許部分的數(shù)據(jù)丟失。
TCP的優(yōu)點是面向連接提供可靠交付,即對數(shù)據(jù)有保證、無差錯的進行運輸。當需要數(shù)據(jù)準確無誤的運輸給對方時,如瀏覽器中需要獲取服務器資源使用的HTTP/HTTPS協(xié)議,需要保證文件準確、無差錯,郵件服務器中使用的SMTP協(xié)議,保證郵件內(nèi)容準確無誤的傳遞給對方,或者是大型應用程序文件,這些都要保證文件的準確、無差錯的運輸給對方,所以一定要基于TCP來運輸,而不是UDP。 加分回答 UDP的應用場景是根據(jù)它的部分特性決定的,如下: - 面向無連接 - 盡最大努力交付 - 面向報文 - 一對多 TCP的應用場景是根據(jù)它的部分特性決定的,如下: - 面向連接 - 單播,一對一 - 可靠交付(確認機制、重傳機制、流量控制、擁塞控制等)
?
總結(jié)
以上是生活随笔為你收集整理的第四次的面试 C++ 面试 (迷茫) + (复习知识点)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 4、传输介质——光纤与光缆
- 下一篇: JVC摄像机mp4视频丢失恢复方法