1. 程式人生 > >C/C++校招面試常考問題

C/C++校招面試常考問題

1、虛擬函式實現機制?

一個virtual函式的類具有一個虛擬函式表,且該類的每一個物件都有一個虛指標,指向該類的虛擬函式表。執行的時候,通過物件自己的虛指標來索引正確的虛擬函式來執行。若基類中虛擬函式的返回型別為基型別的指標或者引用,則派生類中override這個虛擬函式的時候需要將返回型別改為派生類型別的引用或者指標。

2、有了malloc/free為什麼還要new/delete?

malloc/free是C/C++中的標準庫函式,new/delete是C++中的運算子;它們都可以用來申請和釋放動態記憶體;對於非內部資料型別,光用malloc/new是無法滿足需求的;物件在構建的時候會自動呼叫建構函式,在消亡之前會自動呼叫解構函式;由於malloc和new是庫函式,不在編譯器的控制權限之內,所以不能將建構函式和解構函式的工作給它完成。所以C++需要一個完成動態構造和分配記憶體的new和一個能完成清理和釋放記憶體的delete。那麼為什麼不將malloc和new刪除掉呢,因為C++程式需要經常呼叫C函式,而且C程式只能呼叫malloc和free

3、overload 、override、 hide三者的區別?(過載、覆蓋、隱藏)

(1)overload

過載函式的引數的個數、順序、型別不同,virtual可有課可無,返回型別不能最為過載條件

(2)override

派生類覆蓋基類的方法

基類和派生類的函式必須名字相同,引數相同,且必須要有virtual關鍵字

(3)hide

派生類中與基類中的函式名字相同但是引數不同,這種情況下,無論是不是有virtual,派生類的函式都會隱藏基類的方法;

如果派生類的函式與基類的函式名字相同引數相同,但是沒有virtual,此時也是屬於hide

4、指標與陣列的區別?

陣列可以在靜態儲存區被建立也可以在堆上,也可以在棧上建立;指標可以隨時指向任意型別的記憶體塊

使用sizeof運算子可以計算出一個數組的長度,但是sizeof只能求出指標型別的大小

5、建構函式為什麼不能是虛擬函式?

(1)虛擬函式都被存放在一個虛擬函式表裡,虛擬函式表其實是存放在物件的記憶體空間裡,如果建構函式是虛的,就需要通過vtable呼叫,物件還沒有構造出來,記憶體空間還沒有,怎麼找vtable,又如何呼叫呢?

(2)虛擬函式是通過父類的指標或者引用呼叫虛擬函式的時候可以呼叫子類的對應的虛擬函式;而建構函式是在建立父類物件的時候自動呼叫的,不可能通過父類的指標或者引用去呼叫,因此建構函式不能是虛擬函式

6、smart pointer實現原理?

一種通用的實現技術就是使用引用級數(reference count),智慧指標將一個計數器與一個物件相關聯,引用計數跟蹤該類有多少個物件共享同一個指標。

7、含引數的巨集與函式的優缺點?

巨集:

優點:在預處理階段完成,不佔用編譯時間,同時減去了函式呼叫的開銷,執行效率較高

缺點:不進行型別檢查,多次巨集替換導致程式碼體積膨脹,而且由於巨集基本上是字串替換,故可能會因為一些引數的作用導致得出錯誤結果

函式:

優點:沒有帶引數的巨集可能帶來的副作用,進行型別檢查,正確性較高

缺點:函式呼叫需要引數、返回地址的進出棧,效率沒有巨集高

8、巨集與列舉的區別?

巨集定義常量不分配記憶體,而列舉是定義變數的一種方式

巨集和列舉的主要區別在於作用的時期和儲存的形式不同,巨集是在預處理階段進行替換工作,程式執行過程中巨集已經不存在;列舉是在程式執行之後起作用的,列舉常量儲存在靜態儲存區,巨集佔用程式碼段空間,列舉除了佔用空間還消耗CPU資源

9、什麼時候需要常量引用?

既需要利用引用提高程式的效率,又保證在資料不被更改,就要使用常引用

10、如何判斷一段程式是由C編譯的還是C++編譯的?

#ifdef __cplusplus//C++編譯器定義了-cpluspluscout << "by c++";
#else
cout << "by c";
#endif
11、C++和C裡面的struct區別?
在C++裡面class和struct的區別就是:class成員的預設許可權是private,struct的是public;還有就是class可以定義模板但是struct不行
12、堆疊溢位一般是什麼記憶體導致的?
(1)沒有對陣列進行邊界檢查,導致陣列越界

(2)沒有回收垃圾資源,導致記憶體洩露,最後記憶體耗盡

(3)迴圈的遞迴呼叫或者太深層次的遞迴呼叫

(4)使用佔用記憶體過大的型別的區域性變數

13、建構函式可以是內聯的

14、const和static的作用?

static關鍵字:

(1)函式體內的static變數的作用範圍是整個函式體,該變數的記憶體只被分配一次,因此其值在下次呼叫的時候還能維持上次的值

(2)類中的static變數屬於整個類物件所有,對於類的所有物件都只有一份複製

(3)類中的static成員函式屬於整個類所有,這個函式不接受this指標,也只能訪問static成員

const關鍵字:

(1)想要避免一個變數被改變,可以加const修飾,在定義的時候還需要對const變數初始化,否則以後沒法改變

(2)類的成員函式,若被const修飾,那麼這個函式就是一個常量函式,保證不修改類的成員變數

15、注意sizeof不是函式是運算子,在計算變數大小的時候可以省略括號,但是在計算型別的大小的時候不能省略

16、例如int arr[3],a和&a雖然值相等,但是兩者的含義不相同,a是陣列首地址,即a[0]的地址,&a是整個陣列物件的地址,&a+1,表示sizeof(int)*3,即a[3],已經越界了

17、類中的const成員變數,在建構函式裡初始化只能在初始化列表初始化,不能在函式體初始化;const static 成員只能在類外初始化,記得要在變數前加上類名作用域;static成員變數也是在類外初始化,但是不能在變數前加上static關鍵字,同時也是需要加上作用域的

18、定義類的成員變數的時候mutable關鍵字的作用?

在const方法中修改成員變數的時候,防止出錯;

19、C++中explicit關鍵字的作用?

禁止將建構函式作為轉換函式,即禁止建構函式進行自動隱式型別轉換

20、C++的多型性?

C++裡的多型性分為靜多型和動多型

靜多型:編譯階段確定執行什麼,主要通過函式過載和運算子過載實現

動多型:執行時確定執行什麼,主要通過虛擬函式實現

21、在對一個類進行sizeof運算的時候,一個類裡面的static變數不佔記憶體,所有的虛擬函式都只佔用4個位元組(32位),因為所有的函式都存放在vtable中,只有一個vpointer指向vtable

22、引用和指標的區別?

(1)引用宣告的時候必須要進行初始化,即繫結物件變數(不能繫結一個常量上,如int &r=1);但指標變數可以在任何時候初始化

(2)一旦一個引用指向一個物件之後,它就不能改變為指向另外一個物件;但是指標可以在任何時候指向任何物件

(3)不能有NULL引用

(4)引用實際上是變數的別名,指標是指向某記憶體,它的內容就是記憶體的地址

23、面試中經常讓寫的一個函式strcpy

這個函式看起來很easy,但是剛接觸程式設計的時候還是寫不出來,菜。。。;

我們在手撕這個函式的程式碼的時候要注意很多地方,我先貼出程式碼,然後再解釋

char * mystrcpy(char *str1, char *str2)
{
if (str1 == nullptr || str2 == nullptr)//1
return " exception";
char* Address_str = str2;
while ((*str1++ = *str2++!) = '\0');//2
return Address_str;
}

(1)我們首先需要判斷一下兩個字串是不是為null,體現程式碼的健壯性

(2)需要判斷一下字串結束的條件

24、在C/C++中<<和>>除了可以表示輸入輸出運算子還可以表示位運算分別是左移和右移

例如:

int i = 1 << 4;
cout << i;

此時i=16;實際上是先將i轉換為二進位制,然後在向左移4位得到的結果就是16

25、陣列和連結串列的區別

(1)陣列是將元素在記憶體中連續存放,由於每個元素佔用記憶體相同,可以通過下標迅速訪問陣列中任何元素。但是如果要在陣列中增加一個元素,需要移動大量元素,在記憶體中空出一個元素的空間,然後將要增加的元素放在其中。同樣的道理,如果想刪除一個元素,同樣需要移動大量元素去填掉被移動的元素。如果應用需要快速訪問資料,很少或不插入和刪除元素,就應該用陣列。

(2)連結串列恰好相反,連結串列中的元素在記憶體中不是順序儲存的,而是通過存在元素中的指標聯絡到一起。比如:上一個元素有個指標指到下一個元素,以此類推,直到最後一個元素。如果要訪問連結串列中一個元素,需要從第一個元素開始,一直找到需要的元素位置。但是增加和刪除一個元素對於連結串列資料結構就非常簡單了,只要修改元素中的指標就可以了。如果應用需要經常插入和刪除元素你就需要用連結串列資料結構了。

26、面向物件的三個基本特徵是:封裝、繼承、多型

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

暫時先更新到這裡,如果還有需要補充,我會回來補充的