c++面試常見問題
1. 指標常量(int *const p)和常量指標的區別(const int *p、int const *p)?
指標常量:本質上是乙個常量,指標用來說明常量的型別,表示該常量是乙個指標型別的常量。在指標常量中,指標自身的值是乙個常量,不可改變,始終指向同乙個位址,在定義的同時必須初始化。(指向的位址是一定的,但其內容可以修改)
常量指標:本質上乙個指標,常量表示指標指向的內容,說明指標指向乙個「常量」。在常量指標中,指標指向的內容是不可改變的,指標好起來好像指向了乙個常量。(指標可以指向其它位址,但其內容不可以改變)
2. 深拷貝和淺拷貝的區別?
淺拷貝:只是對指標的拷貝,拷貝後兩個指標指向同乙個記憶體空間。
當物件中存在指標成員時,淺拷貝帶來的問題本質是析構函式釋放多次記憶體,可使用std::shared_ptr解決這個問題。
3. 類的三個基本特徵是什麼、類的型別相容規則是什麼?
封裝:**模組化
繼承:**重用
多型:介面重用
1) 派生類物件可以隱含轉換為基類物件;
2) 派生類物件可以初始化為基類的引用;
3) 派生類的指標可以隱含的轉換為基類的指標;
4. 指標和引用的區別?
不同點:
1) 指標是乙個實體,而引用是乙個別名;
2) 引用在使用時無需解引用(*),指標需要解引用;
3) 引用只能在定義時初始化一次,之後不可變;指標可變;
4) 引用沒有const,指標有const;
5) 引用不能為空,指標可以為空;
6) sizeof 引用得到的是變數(物件)的大小;而sizeof指標得到本身大小;
5. 右值引用和move語義
1) 左值和右值的區別:
左值是表示式結束後依然持久存在的物件;
右值是表示式結束後不存在的臨時物件;
2) c++11特性中用&表示左值引用,用&&表示右值引用;
3) move語義允許乙個物件在特定的情形下,取其它物件的資源;
6. 普通函式可以呼叫const函式,也可以呼叫非const函式,但是const物件只能呼叫const函式。
7. 函式指標和指標函式的區別?
1) 函式指標 :乙個函式總是占用一段連續的記憶體區,函式名作為所佔記憶體區首位址,把首位址賦予乙個指標變數,指向該函式,通過指標變數呼叫這個函式。// int (*f) (int x);
8. 記憶體分為哪些區?
堆(後進先出)、棧(先進後出)、全域性區(靜態區)、文字常量區、程式**區
9. static關鍵字的作用
1) 函式體內static變數作用範圍為該函式體,不同於auto變數,記憶體只分配一次,下次呼叫仍為上次的值。
2) 模組內static變數可以模組內訪問,不能被模組外訪問;
3) 模組內static函式限制模組內;
4) 型別static成員變數屬於整個類,只有乙份拷貝;
5) 類中static成員函式屬於類,只能訪問static成員變數,不接受this指標;
10. inline內聯關鍵字的作用
1) 函式呼叫時**替換(省去呼叫開銷,效率高,但占用空間開銷)
2) 變數自動替換(**中形參和實參替換)
11. 禁止異常傳遞到析構函式中的原因:
1) 能夠在異常傳遞的堆疊碾轉開解的過程中防止terminate被呼叫;
2) 幫助確保析構函式總能完成我們希望它做的事;
12. 兩個map進行拷貝:先swap,然後std::copy()
13. 什麼是多型?多型的分類?多型實現原理?
定義:多型就是將基類型別的指標或者引用指向派生型別的物件。多型通過虛函式機制實現。
作用:介面重用。
多型的分類:靜態多型、動態多型(多型性具體體現在編譯和執行兩個階段)
靜態多型:通過函式的過載(編譯時)來實現的。
動態多型:通過虛函式(執行時)來實現的。
實現原理:
1) 當類中存在虛函式時,編譯器會在類中自動生成乙個虛函式表;
2) 虛函式表是乙個儲存類成員函式指標的資料結構;
3) 虛函式表由編譯器自動生成和維護;
4) virtual 修飾的成員函式會被編譯器放入虛函式表中;
5) 存在虛函式時,編譯器會為物件自動生成乙個指向虛函式表的指標(通常稱之為 vptr 指標);
14. 虛函式和純虛函式有什麼區別?
從基類的角度出發,如果乙個類中宣告了虛函式,這個函式是要在類中實現的,它的作用是為了能讓這個函式在他的子類中能被重寫,實現動態多型。純虛函式,只是乙個介面,乙個函式宣告,並沒有在宣告他的類中實現。對於子類來說它可以不重寫基類中的虛函式,但是他必須要將基類中的純虛函式實現。虛函式既繼承介面的同時也繼承了基類的實現,純虛函式關注的是介面的統一性,實現完全由子類來完成。
15. 為什麼要引入抽象類和純虛函式?
為了方便使用多型特性,在很多情況下由基類生成物件是很不合理的,純虛函式在基類中是沒有定義的,要求在子類必須加以實現,這種包含了純虛函式的基類被稱為抽象類,不能被例項化,如果子類沒有實現純虛函式,那麼它他也是乙個抽象類。
16. 虛函式如何實現的?
1) 虛函式是通過一張虛函式表實現的,有多少個虛函式,就有多少個指標;
2) 在這個表中,主要是乙個類的虛函式的位址表,這張表解決了繼承、覆蓋的問題;
3) 實際上在編譯的時候,編譯器會自動加上虛表
4) 虛函式的作用實現動態聯編,也就是說在程式執行階段動態的選擇合適的成員函式,在定義了虛函式之後,可以在基類的派生類中對虛函式重新定義。
5) 虛表的使用方法是如果派生類在自己定義中沒有修改基類的虛函式,我們就指向基類的虛函式;如果派生類改寫了基類的虛函式,這時續表則將原來指向基類的虛函式的位址替換為指向自身虛函式的指標。
6) 必須通過基類型別的引用或指標進行函式呼叫才會發生多型。
17. 為什麼建構函式不能為虛函式?
答:虛函式採用一種虛呼叫的方法。需呼叫是一種可以在只有部分資訊的情況下工作的機制。如果建立乙個物件,則需要知道物件的準確型別,因此建構函式不能為虛函式。
18. vector和list的區別?
vector資料結構:vector和陣列類似,擁有一段連續的記憶體空間,並且起始位址不變。因此能高效的進行隨機訪問,時間複雜度為o(1);但因為記憶體空間是連續的,所以在進行插入和刪除操作時,會造成記憶體塊的拷貝,時間複雜度為o(n)。另外,當陣列中記憶體空間不夠時,會重新申請一塊記憶體空間並進行記憶體拷貝。
list資料結構:list是由雙向鍊錶實現的,因此一段不連續的記憶體空間。只能通過指標訪問資料,所以list的隨機訪問非常沒有效率,時間複雜度為o(n);但由於鍊錶的特點,能高效地進行插入和刪除。
結論:vector擁有一段連續的記憶體空間,能很好的支援隨機訪問,因此vector::iterator支援「+」,「+=」,「<」等操作符。
list的記憶體空間可以是不連續,它不支援隨機訪問,因此list::iterator則不支援「+」、「+=」、「<」等
總之,如果需要高效的隨機訪問,而不在乎插入和刪除的效率,使用vector;如果需要大量的插入和刪除,而不關心隨機訪問,則應使用list。
19. 多型類中的虛函式表是編譯時,還是執行時建立的?
答案:虛函式表是在編譯期就建立了,各個虛函式這時被組織成了乙個虛函式的入口位址的陣列。而物件的隱藏成員--虛函式表指標是在執行期--也就是建構函式被呼叫時進行初始化的,這是實現多型的關鍵。
20. dll動態載入和靜態載入(隱式載入的區別?
dll有兩種呼叫方式:
1) 靜態載入:隱式載入(需要.lib和.dll)
隱式載入就是在程式編譯的時候就將dll編譯到可執行檔案中,這種載入方式呼叫方便,程式發布的時候可以不用講dll帶著。
缺點:這樣編譯出來後,程式會很大。
2) 動態載入:顯式載入(需要.dll)
dll顯式載入時指在程式執行過程中,需要用到dll裡的函式時,再動態載入dll到記憶體中,這種載入方式因為是在程式執行後再載入的,所以可以讓程式啟動更快,而且dll的維護更容易,使得程式如果需要更新,很多時候直接更新dll,而不用重新安裝程式,只是這種載入方式,函式呼叫稍微複雜一點。
C 面試常見問題
1.引用和指標的區別 區別 1 引用不能為空,指標可以為空 2 引用必須初始化,指標不需要 3 引用初始化以後不能改變,指標可以改變初始化物件後的值 4 引用訪問物件後是直接訪問,指標訪問物件是間接訪問 5 引用大小是所引用物件的大小,指標大小是指標類本身的大小 6 引用沒有const,指標有con...
C 面試常見問題
智慧型指標的作用是管理乙個指標,因為存在以下這種情況 申請的空間在函式結束時忘記釋放,造成記憶體洩漏。使用智慧型指標可以很大程度上的避免這個問題,因為智慧型指標就是乙個類,當超出了類的作用域是,類會自動呼叫析構函式,析構函式會自動釋放資源。所以智慧型指標的作用原理就是在函式結束時自動釋放記憶體空間,...
C 面試常見問題(五)
使用動態庫進行鏈結。動態庫 so dll 具體的區別下面這篇部落格講得比較詳細。大家可以移步至 c 靜態庫與動態庫 因此乙個物件的大小 所有非靜態成員大小的總和 由以上分析可以得到菱形繼承物件的記憶體大小問題 includeusing namespace std class a 大小為8,int 4...