1. 程式人生 > 實用技巧 >海康威視c++實習生面試資料

海康威視c++實習生面試資料

  • 面對物件

1. 三大特性:封裝,繼承,多型

2.封裝性:資料和程式碼捆綁在一起,避免外界干擾和不確定性訪問。封裝可以使得程式碼模組化。

3.繼承性:讓某種型別物件獲得另一個型別物件的屬性和方法。繼承可以擴充套件已存在的程式碼。

4.多型性:同一事物表現出不同事物的能力,即向不同物件傳送同一訊息,不同的物件在接收時會產生不同的行為(過載實現編譯時多型,虛擬函式實現執行時多型)。多型的目的則是為了介面重用。

5. 多型的底層實現:C++多型性是通過虛擬函式來實現的,虛擬函式允許子類重新定義成員函式,而子類重新定義父類的做法稱為覆蓋(override),或者稱為重寫。

6. 多型的底層實現:在C++中,通過基類的引用(或指標)呼叫虛擬函式時,發生動態繫結,引用(或指標)既可以指向基類也可以指向派生類,引用和指標的靜態型別和動態型別可以不同,這是c++用以支援多型性的基石。

  • C++

1. STL(標準模板庫):

(1)STL的一個重要特點是資料結構和演算法的分離

(2)STL另一個重要特性是它不是面向物件的。為了具有足夠通用性,STL主要依賴於模板而不是封裝,繼承和虛擬函式(多型性)——OOP的三個要素。你在STL中找不到任何明顯的類繼承關係。這好像是一種倒退,但這正好是使得STL的元件具有廣泛通用性的底層特徵。另外,由於STL是基於模板,行內函數的使用使得生成的程式碼短小高效。

(3)從邏輯層次來看,在STL中體現了泛型化程式設計的思想,引入了諸多新的名詞。

(4)從實現層次看,整個STL是以一種型別引數化的方式實現的,這種方式基於一個在早先C++標準中沒有出現的語言特性--模板(template)。

2.STL中六大元件:(1)容器(2)迭代器(3)演算法(4)仿函式(5)介面卡(6)分配器

3. 容器:(1)序列式容器:vector,deque,list(2)關聯式容器:set/multiset,map/multimap

4.vector和list的區別:

(1)vector和陣列類似,擁有一段連續的記憶體空間,並且起始地址不變。因此,它能夠高效地進行隨機存取,時間複雜度是O(1)。但是,因為其記憶體空間是連續的,所以在進行插入和刪除操作時,會造成記憶體塊的拷貝,因此時間複雜度為O(n)。另外,當陣列記憶體空間不夠時,會重新申請一塊內動空間並進行記憶體拷貝。

(2)list是由雙向連結串列實現的,因此記憶體空間是不連續的。其只能通過指標訪問資料,所以list的隨機存取效率很低,時間複雜度為O(n)。不過由於連結串列自身的特點,能夠進行高效的插入和刪除。

(3)vector和list對於迭代器的支援不同。相同點在於,vector< int >::iterator和list< int >::iterator都過載了 “++ ”操作。而不同點在於,在vector中,iterator支援 ”+“、”+=“,”<"等操作。而list中則不支援。

5.vector的risize底層實現:每個動態陣列都分配有一定容量,當儲存的資料達到容量的上限的時候,就重新分配記憶體。一般來說後面的記憶體已經被佔用了,在後面增加是不可能的。resize是重新開闢了一個數組,把之前的值放到複製到新開闢的陣列中來。

6. c++智慧指標:

(1)c++裡面的四個智慧指標,auto_ptr,unique_ptr,shared_ptr,weak_ptr,其中後三個是c++11支援,並且第一個已經被c++11棄用

(2)使用原因:智慧指標的作用是管理一個指標,因為存在以下這種情況:申請的空間在函式結束時忘記釋放,造成記憶體洩漏。使用智慧指標可以很大程度上的避免這個問題,因為智慧指標是一個類,當超出了類的例項物件的作用域時,會自動呼叫物件的解構函式,解構函式會自動釋放資源。所以智慧指標的作用原理就是在函式結束時自動釋放記憶體空間,不需要手動釋放記憶體空間。

(3)auto_ptr:採用所有權模式。p2剝奪了p1的所有權,但是當程式執行時訪問p1將會報錯。所以auto_ptr的缺點是:存在潛在的記憶體崩潰問題。

(4)unique_ptr:實現獨佔式擁有或嚴格擁有概念,保證同一時間內只有一個智慧指標可以指向該物件。它對於避免資源洩露(例如“以new建立物件後因為發生異常而忘記呼叫delete”)特別有用,可以通過標準庫的move()函式實現指標轉移。

(5)shared_ptr:實現共享式擁有概念。多個智慧指標可以指向相同物件,該物件和其相關資源會在“最後一個引用被銷燬”時候釋放。從名字share就可以看出了資源可以被多個指標共享,它使用計數機制來表明資源被幾個指標共享。

(6)weak_ptr:是一種不控制物件生命週期的智慧指標, weak_ptr 設計的目的是為配合 shared_ptr 而引入的一種智慧指標來協助 shared_ptr 工作, 它只可以從一個 shared_ptr 或另一個 weak_ptr 物件構造, 它的構造和析構不會引起引用記數的增加或減少。

7.Qt是一個跨平臺的C++應用程式開發框架。它提供給開發者建立圖形使用者介面所需的功能,廣泛用於開發GUI程式,也可用於開發非GUI程式。Qt是完全面向物件的,很容易擴充套件,並且允許真正地元件程式設計。Qt使用標準的C++和特殊的程式碼生成擴充套件(稱為元物件編譯器Meta Object Compiler, moc)以及一些巨集。

8.訊號槽是 Qt 框架引以為豪的機制之一。所謂訊號槽,實際就是觀察者模式。當某個事件發生之後,比如,按鈕檢測到自己被點選了一下,它就會發出一個訊號(signal)。這種發出是沒有目的的,類似廣播。如果有物件對這個訊號感興趣,它就會使用連線(connect)函式,意思是,將想要處理的訊號和自己的一個函式(稱為槽(slot))繫結來處理這個訊號。也就是說,當訊號發出時,被連線的槽函式會自動被回撥。這就類似觀察者模式:當發生了感興趣的事件,某一個操作就會被自動觸發。(這裡提一句,Qt 的訊號槽使用了額外的處理來實現,並不是 GoF 經典的觀察者模式的實現方式。)

訊號和槽是Qt特有的資訊傳輸機制,是Qt設計程式的重要基礎,它可以讓互不干擾的物件建立一種聯絡。

槽的本質是類的成員函式,其引數可以是任意型別的。和普通C++成員函式幾乎沒有區別,它可以是虛擬函式;也可以被過載;可以是公有的、保護的、私有的、也可以被其他C++成員函式呼叫。

唯一區別的是:槽可以與訊號連線在一起,每當和槽連線的訊號被髮射的時候,就會呼叫這個槽。

9. 常見的設計模式:

(1)工廠模式:簡單工廠模式、工廠方法模式、抽象工廠模式。工廠模式的主要作用是封裝物件的建立,分離物件的建立和操作過程,用於批量管理物件的建立過程,便於程式的維護和擴充套件。

(2)單例模式:保證一個類只有一個例項,並提供一個訪問它的全域性訪問點,使得系統中只有唯一的一個物件例項。常用於管理資源,如日誌、執行緒池。

(3)策略模式:策略模式定義了一系列的演算法,並將每一個演算法封裝起來,而且使它們還可以相互替換。策略模式讓演算法獨立於使用它的客戶而獨立變化。

10. c++11新特性:

(1)C++11 引入了 nullptr 關鍵字,專門用來區分空指標、0

(2)C++11 引入了 auto 和 decltype 這兩個關鍵字實現了型別推導,讓編譯器來操心變數的型別

(3)C++11 引入了基於範圍的迭代寫法,我們擁有了能夠寫出像 Python 一樣簡潔的迴圈語句。

(4)std::array 儲存在棧記憶體中,相比堆記憶體中的 std::vector,我們能夠靈活的訪問這裡面的元素,從而獲得更高的效能。std::array 會在編譯時建立一個固定大小的陣列,std::array 不能夠被隱式的轉換成指標,使用 std::array只需指定其型別和大小即可

(5)C++11 引入了兩組無序容器:std::unordered_map/std::unordered_multimap 和 std::unordered_set/std::unordered_multiset。無序容器中的元素是不進行排序的,內部通過 Hash 表實現,插入和搜尋元素的平均複雜度為 O(constant)。

  • 資料結構

1. B+樹和B樹:

(1)B+樹非葉子節點只儲存key,只有葉子結點儲存value,葉子結點包含了這棵樹的所有鍵值,每個葉子結點有一個指向相鄰葉子結點的指標,這樣可以降低B樹的高度。

(2)B+樹相比於B樹的優勢:(1)B+樹單一節點儲存更多的元素,使得查詢的IO次數更少(2)B+樹所有查詢都要查詢到葉子節點,查詢效率更加穩定(3)B+樹所有葉子節點形成有序連結串列,便於範圍查詢,更有利於對資料庫的掃描

2. B+樹和B-樹的區別:

(1)B-樹的葉bai子結點不含任何資訊,而B+樹的葉子結點含資訊

(2)B-樹上的葉子結點不會指向它的兄弟結點,而B+樹上的葉子結點會指向它的兄弟結點

(3)B-樹只能進行分割槽間查詢,而B+樹上可以有兩種查詢:順序查詢和分割槽間查詢

3. 紅黑樹的五大特性:

(1)節點是紅色或黑色。

(2)根節點是黑色。

(3)每個葉子節點都是黑色的空節點(NIL節點)。

(4)每個紅色節點的兩個子節點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)

(5)從任一節點到其每個葉子的所有路徑都包含相同數目的黑色節點。

4. 紅黑樹插入刪除操作的三個後續操作:變色,左旋,右旋

5.基本的排序演算法有哪些:

(1)插入排序,時間複雜度O(n^2),空間複雜度O(1),穩定

思想:將無序序列中的各元素依次插入到已經有序的線性表中,從而得到一個新的序列

(2)希爾排序,時間複雜度O(nlog2n),空間複雜度O(1),不穩定

(3)快速排序,時間複雜度O(nlog2n),空間複雜度O(log2n),不穩定

(4)氣泡排序,時間複雜度O(n^2),空間複雜度O(1),穩定

(5)簡單排序,時間複雜度O(n^2),空間複雜度O(1),不穩定

(6)堆排序,時間複雜度O(nlog2n),空間複雜度O(1),不穩定

(7)歸併排序,時間複雜度O(nlog2n),空間複雜度O(n),穩定

6. 快速排序的思路:通過一趟排序將待排序記錄分割成獨的兩部分,其中一部分記錄的關鍵字均比另一部分記錄的關鍵字小,再分別對這兩部分記錄繼續進行排序,以達到整個序列有序

  • 網路程式設計

1.socket:即套接字,用於描述地址和埠,是一個通訊鏈的控制代碼。應用程式通過socket向網路發出請求或者回應。

2. sockets程式設計有三種:流式套接字(SOCK_STREAM),資料報套接字(SOCK_DGRAM),原始套接字(SOCK_RAW);前兩種較常用。基於TCP的socket程式設計是採用的流式套接字。

(1)SOCK_STREAM:位元組流傳輸,表示面向連線的資料傳輸方式。資料可以準確無誤地到達另一臺計算機,如果損壞或丟失,可以重新發送,但效率相對較慢。常用的HTTP協議就使用SOCK_STREAM傳輸資料,因為要確保資料的正確性,否則網頁不能正常解析。

(2)SOCK_DGRAM:資料報傳輸,表示無連線的資料傳輸方式。計算機只管傳輸資料,不作資料校驗,如果資料在傳輸中損壞,或者沒有到達另一臺計算機,是沒有辦法補救的。也就是說,資料錯了就錯了,無法重傳。因為SOCK_DGRAM所做的校驗工作少,所以效率比SOCK_STREAM高。

3.服務端:建立socket,宣告自身的埠號和地址並繫結到socket,使用listen開啟監聽,然後不斷用accept去檢視是否有連線,如果有,捕獲socket,並通過recv獲取訊息的內容,通訊完成後呼叫closeSocket關閉這個對應accept到的socket,如果不再需要等待任何客戶端連線,那麼用closeSocket關閉掉自身的socket。

4.客戶端:建立socket,通過埠號和地址確定目標伺服器,使用Connect連線到伺服器,send傳送訊息,等待處理,通訊完成後呼叫closeSocket關閉socket

5. 高併發:伺服器使用select函式,客戶端使用多執行緒

6. 同步和非同步的區別:

(1)同步:所有的操作都做完,才返回給使用者。這樣使用者線上等待的時間太長,給使用者一種卡死了的感覺(就是系統遷移中,點選了遷移,介面就不動了,但是程式還在執行,卡死了的感覺)。這種情況下,使用者不能關閉介面,如果關閉了,即遷移程式就中斷了。

(2)非同步:將使用者請求放入訊息佇列,並反饋給使用者,系統遷移程式已經啟動,你可以關閉瀏覽器了。然後程式再慢慢地去寫入資料庫去。這就是非同步。但是使用者沒有卡死的感覺,會告訴你,你的請求系統已經響應了。你可以關閉介面了。

(3)同步,是所有的操作都做完,才返回給使用者結果。即寫完資料庫之後,再響應使用者,使用者體驗不好。非同步,不用等所有操作都做完,就相應使用者請求。即先響應使用者請求,然後慢慢去寫資料庫,使用者體驗較好。

(4)為了避免短時間大量的資料庫操作,就使用快取機制,也就是訊息佇列。先將資料放入訊息佇列,然後再慢慢寫入資料庫。引入訊息佇列機制,雖然可以保證使用者請求的快速響應,但是並沒有使得我資料遷移的時間變短(即80萬條資料寫入mysql需要1個小時,用了redis之後,還是需要1個小時,只是保證使用者的請求的快速響應。使用者輸入完http url請求之後,就可以把瀏覽器關閉了,幹別的去了。如果不用redis,瀏覽器不能關閉)。

  • 計算機網路

1.TCP為什麼要進行三次握手:(1)因為通道不可靠,而 TCP 想在不可靠通道上建立可靠地傳輸,那麼三次通訊是理論上的最小值(2)因為雙方都需要確認對方收到了自己傳送的序列號,確認過程最少要進行三次通訊(3)為了防止已失效的連線請求報文段突然又傳送到了服務端,因而產生錯誤。

2. TCP 為什麼要進行四次揮手:

因為 TCP 是全雙工模式,客戶端請求關閉連線後,客戶端向服務端的連線關閉(一二次揮手),服務端繼續傳輸之前沒傳完的資料給客戶端(資料傳輸),服務端向客戶端的連線關閉(三四次揮手)。所以 TCP 釋放連線時伺服器的 ACK 和 FIN 是分開發送的(中間隔著資料傳輸),而 TCP 建立連線時伺服器的 ACK 和 SYN 是一起傳送的(第二次握手),所以 TCP 建立連線需要三次,而釋放連線則需要四次。

3. 擁塞控制:

TCP的擁塞控制:(1)原因:擁塞控制就是防止過多的資料注入到網路中,可以使網路中的路由器或鏈路不致過載(2)解決方法:慢啟動( slow-start );擁塞避免( congestion avoidance );快重傳( fast retransmit );快恢復( fast recovery)

4.TCP和UDP的區別:

(1)TCP面向連線、UDP是無連線的

(2)TCP提供可靠的服務,UDP不保證可靠交付

(3)TCP連線只能是點對點的,UDP支援一對多、多對一、多對多的互動通訊

(4)TCP面向位元組流(可能會出現黏包問題),UDP是面向報文的(不會出現黏包問題)

(5)UDP沒有擁塞控制,因此網路出現擁塞不會使源主機的傳送速率降低(對實時應用很有用,如IP電話,實時視訊會議等)

(6)TCP首部開銷20位元組;UDP的首部開銷小,只有8位元組

5.TCP的黏包問題:

(1)原因:TCP 是一個基於位元組流的傳輸服務,“流” 意味著 TCP 所傳輸的資料是沒有邊界的,所以可能會出現兩個資料包黏在一起的情況

(2)解決辦法:傳送定長包;包頭加上包體長度;在資料包之間設定邊界,如新增特殊符號 \r\n 標記;使用更加複雜的應用層協議

6.基本I/O模型有哪些:(1)同步阻塞I/O模型(2)同步非阻塞I/O模型(3)I/O多路複用模型(4)訊號驅動I/O模型(5)非同步I/O模型

7.程序:程序是對執行時程式的封裝,是系統進行資源排程和分配的基本單位,實現了作業系統的併發

  • 作業系統

1. 程序:程序是對執行時程式的封裝,是系統進行資源排程和分配的基本單位,實現了作業系統的併發

2. 執行緒:執行緒是程序的子任務,是CPU排程和分派的基本單位

3. 程序和執行緒之間的區別:(1)一個程式至少有一個程序,一個程序至少有一個執行緒,執行緒依賴於程序而存在(2)程序在執行過程中擁有獨立的記憶體單元,而多個執行緒共享程序的記憶體

4. 程序的狀態:(1)就緒狀態(2)執行狀態(3)阻塞狀態

5. 程序間通訊的幾種方式:(1)管道(2)訊息佇列(3)共享記憶體(4)訊號量(5)巢狀字

6. 程序排程演算法:(1)先來先服務排程演算法FCFS(2)最短作業優先排程演算法SJF(3)高優先順序排程演算法HPF(4)時間片輪轉排程演算法(可搶佔的)RR(5)多級反饋佇列排程演算法

7. 死鎖:兩個或多個程序無限期阻塞、 相互等待的一種狀態

8. 死鎖產生的四個必要條件:(1)互斥(2)佔有並等待(3)非搶佔(4)迴圈等待

9. 死鎖處理:

(1)預防死鎖:破壞產生死鎖的4個必要條件中的一個或者多個;實現起來比較簡單,但是如果限制過於嚴格會降低系統資源利用率以及吞吐量

(2)避免死鎖:在資源的動態分配中,防止系統進入不安全狀態

(3)監測死鎖

(4)解除死鎖:程序終止和資源搶佔