C 常見問答面試題詳解

2021-09-24 05:35:13 字數 4697 閱讀 8441

1.請說出static和const關鍵字盡可能多的作用

static關鍵字至少有下列n個作用:   

(1)函式體內static變數的作用範圍為該函式體,不同於auto變數,該變數的記憶體只被分配一次,因此其值在下次呼叫時仍維持上次的值;   

(2)在模組內的static全域性變數可以被模組內所用函式訪問,但不能被模組外其它函式訪問;   

(3)在模組內的static函式只可被這一模組內的其它函式呼叫,這個函式的使用範圍被限制在宣告它的模組內;   

(4)在類中的static成員變數屬於整個類所擁有,對類的所有物件只有乙份拷貝;   

(5)在類中的static成員函式屬於整個類所擁有,這個函式不接收this指標,因而只能訪問類的static成員變數。    

const關鍵字至少有下列n個作用:   

(1)欲阻止乙個變數被改變,可以使用const關鍵字。在定義該const變數時,通常需要對它進行初始化,因為以後就沒有機會再去改變它了;   

(2)對指標來說,可以指定指標本身為const,也可以指定指標所指的資料為const,或二者同時指定為const;   

(3)在乙個函式宣告中,const可以修飾形參,表明它是乙個輸入引數,在函式內部不能改變其值;   

(4)對於類的成員函式,若指定其為const型別,則表明其是乙個常函式,不能修改類的 成員變數;   

(5)對於類的成員函式,有時候必須指定其返回值為const型別,以使得其返回值不為「左值」。例如:   

const classa operator*(const classa& a1,const classa& a2);   

operator*的返回結果必須是乙個const物件。如果不是,這樣的****也不會編譯出錯:   

classa a, b, c;   

(a * b) = c; // 對a*b的結果賦值   

操作(a * b) = c顯然不符合程式設計者的初衷,也沒有任何意義。  

2.請說一下c/c++ 中指標和引用的區別?

參考回答:

1.指標有自己的一塊空間,而引用只是乙個別名;

2.使用sizeof看乙個指標的大小是4,而引用則是被引用物件的大小;

3.指標可以被初始化為null,而引用必須被初始化且必須是乙個已有物件 的引用;

4.作為引數傳遞時,指標需要被解引用才可以對物件進行操作,而直接對引 用的修改都會改變引用所指向的物件;

5.可以有const指標,但是沒有const引用;

6.指標在使用中可以指向其它物件,但是引用只能是乙個物件的引用,不能 被改變;

7.指標可以有多級指標(**p),而引用至於一級;

8.指標和引用使用++運算子的意義不一樣;

9.如果返回動態記憶體分配的物件或者記憶體,必須使用指標,引用可能引起記憶體洩露。

3.請你回答一下為什麼析構函式必須是虛函式?為什麼c++預設的析構函式不是虛函式

考點:虛函式 析構函式

參考回答:

將可能會被繼承的父類的析構函式設定為虛函式,可以保證當我們new乙個子類,然後使用基類指標指向該子類物件,釋放基類指標時可以釋放掉子類的空間,防止記憶體洩漏。

c++預設的析構函式不是虛函式是因為虛函式需要額外的虛函式表和虛表指標,占用額外的記憶體。而對於不會被繼承的類來說,其析構函式如果是虛函式,就會浪費記憶體。因此c++預設的析構函式不是虛函式,而是只有當需要當作父類時,設定為虛函式。

4.請你來說一下fork函式

fork:建立乙個和當前程序映像一樣的程序可以通過fork( )系統呼叫:

#include

#include

pid_t fork(void);

成功呼叫fork( )會建立乙個新的程序,它幾乎與呼叫fork( )的程序一模一樣,這兩個程序都會繼續執行。在子程序中,成功的fork( )呼叫會返回0。在父程序中fork( )返回子程序的pid。如果出現錯誤,fork( )返回乙個負值。

5.請你來說一下map和set有什麼區別,分別又是怎麼實現的?

參考回答:

map和set都是c++的關聯容器,其底層實現都是紅黑樹(rb-tree)。由於 map 和set所開放的各種操作介面,rb-tree 也都提供了,所以幾乎所有的 map 和set的操作行為,都只是轉調 rb-tree 的操作行為。

map和set區別在於:

(2)set的迭代器是const的,不允許修改元素的值;map允許修改value,但不允許修改key。其原因是因為map和set是根據關鍵字排序來保證其有序性的,如果允許修改key的話,那麼首先需要刪除該鍵,然後調節平衡,再插入修改後的鍵值,調節平衡,如此一來,嚴重破壞了map和set的結構,導致iterator失效,不知道應該指向改變前的位置,還是指向改變後的位置。所以stl中將set的迭代器設定成const,不允許修改迭代器的值;而map的迭代器則不允許修改key值,允許修改value值。

6.請你來說一下c++中struct和class的區別

參考回答:

在c++中,可以用struct和class定義類,都可以繼承。區別在於:structural的預設繼承許可權和預設訪問許可權是public,而class的預設繼承許可權和預設訪問許可權是private。

7.請你來說一下乙個c++原始檔從文字到可執行檔案經歷的過程?

參考回答:

對於c++原始檔,從文字到可執行檔案一般需要四個過程:

預處理階段:對源**檔案中檔案包含關係(標頭檔案)、預編譯語句(巨集定義)進行分析和替換,生成預編譯檔案。

編譯階段:將經過預處理後的預編譯檔案轉換成特定彙編**,生成彙編檔案

彙編階段:將編譯階段生成的彙編檔案轉化成機器碼,生成可重定位目標檔案

8.請你說一說c++的記憶體管理是怎樣的?

參考回答:

在c++中,虛擬記憶體分為**段、資料段、bss段、堆區、檔案對映區以及棧區六部分。

**段:包括唯讀儲存區和文字區,其中唯讀儲存區儲存字串常量,文字區儲存程式的機器**。

資料段:儲存程式中已初始化的全域性變數和靜態變數

bss 段:儲存未初始化的全域性變數和靜態變數(區域性+全域性),以及所有被初始化為0的全域性變數和靜態變數。

堆區:呼叫new/malloc函式時在堆區動態分配記憶體,同時需要呼叫delete/free來手動釋放申請的記憶體。

對映區:儲存動態鏈結庫以及呼叫mmap函式進行的檔案對映

9.請你來回答一下new和malloc的區別

考回答:

1、new分配記憶體按照資料型別進行分配,malloc分配記憶體按照指定的大小分配;

2、new返回的是指定物件的指標,而malloc返回的是void*,因此malloc的返回值一般都需要進行型別轉化。

3、new不僅分配一段記憶體,而且會呼叫建構函式,malloc不會。

4、new分配的記憶體要用delete銷毀,malloc要用free來銷毀;delete銷毀的時候會呼叫物件的析構函式,而free則不會。

5、new是乙個操作符可以過載,malloc是乙個庫函式。

6、malloc分配的記憶體不夠的時候,可以用realloc擴容。擴容的原理?new沒用這樣操作。

7、new如果分配失敗了會丟擲bad_malloc的異常,而malloc失敗了會返回null。

8、申請陣列時: new一次分配所有記憶體,多次呼叫建構函式,搭配使用delete,delete多次呼叫析構函式,銷毀陣列中的每個物件。而malloc則只能sizeof(int) * n。

10.遊戲伺服器應該為每個使用者開闢乙個執行緒還是乙個程序,為什麼?

參考回答:

遊戲伺服器應該為每個使用者開闢乙個程序。因為同一程序間的執行緒會相互影響,乙個執行緒死掉會影響其他執行緒,從而導致程序崩潰。因此為了保證不同使用者之間不會相互影響,應該為每個使用者開闢乙個程序

11.請你回答一下靜態變數什麼時候初始化

參考回答:

靜態變數儲存在虛擬位址空間的資料段和bss段,c語言中其在**執行之前初始化,屬於編譯期初始化。而c++中由於引入物件,物件生成必須呼叫建構函式,因此c++規定全域性或區域性靜態物件當且僅當物件首次用到時進行構造

12.stl中vector的實現原理 (衍生:map, set等實現原理)

vector的資料安排以及操作方式,與array非常相似。兩者的唯一區別在於空間的運用的靈活性。array是靜態空間,一旦配置了就不能改變;要換個大(或小)一點的房子,可以,一切瑣細都得由客戶端自己來:首先配置一塊新空間,然後將元素從舊址一一搬往新址,再把原來的空間釋還給系統。vector是動態空間,隨著元素的加入,它的內部機制會自行擴充空間以容納新元素。因此,vector的運用對於記憶體的合理利用與運用的靈活性有很大的幫助,我們再也不必因為害怕空間不足而一開始要求乙個大塊頭的array了,我們可以安心使用array,吃多少用多少。 

vector的實現技術,關鍵在於其對大小的控制以及重新配置時的資料移動效率。一旦vector的舊有空間滿載,如果客戶端每新增乙個元素,vector的內部只是擴充乙個元素的空間,實為不智。因為所謂擴充空間(不論多大),一如稍早所說,是」  配置新空間/資料移動/釋還舊空間  「的大工程,時間成本很高,應該加入某種未雨綢繆的考慮。稍後我們便可看到sgi vector的空間配置策略了。 

另外,由於  vector維護的是乙個連續線性空間,所以vector支援隨機訪問  。 

注意:vector動態增加大小時,並不是在原空間之後持續新空間(因為無法保證原空間之後尚有可供配置的空間),而是以原大小的兩倍另外配置一塊較大的空間,然後將原內容拷貝過來,然後才開始在原內容之後構造新元素,並釋放原空間。因此,  對vector的任何操作,一旦引起空間重新配置,指向原vector的所有迭代器就都失效了  。這是程式設計師易犯的乙個錯誤,務需小心。

面試題問答

區別通過作用體現 作用 用於呼叫陣列的每個元素,並將元素傳遞給 函式,函式的三個分別是value,index,arr 陣列本身 不足 不能同時遍歷多個集合,在遍歷的時候無法修改和刪除集合資料,方法不能使用break,continue語句跳出迴圈,或者使用return從函式體返回,對於空陣列不會執行 ...

常見C 面試題

1.解釋堆 heap 和棧 stack 的區別。答 堆 1.由程式設計師分配釋放,存放new出來的物件 2.不連續,類似於鍊錶,大小取決於計算機系統的虛擬記憶體 棧 1.由編譯器自動分配釋放,存放函式引數值或區域性變數等。2.連續的儲存區域 2m左右 空間不足會提示棧溢位 overflow 2.論述...

C 常見面試題

1.c中static有什麼作用 1 隱藏。當我們同時編譯多個檔案時,所有未加static字首的全域性變數和函式都具有全域性可見性,故使用static在不同的檔案中定義同名函式和同名變數,而不必擔心命名衝突。2 static的第二個作用是保持變數內容的持久。儲存在靜態資料區的變數會在程式剛開始執行時就...