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