C/C++面試經典
阿新 • • 發佈:2019-01-31
這裡彙總一下面試的時候經常會被問到的一些問題。
1.const 有什麼用途
1:定義只讀變數,即常量2:修飾函式的引數和函式的返回值
3: 修飾函式的定義體,這裡的函式為類的成員函式,被const修飾的成員函式代表不修改成員變數的值
2.指標和引用的區別
1:引用是變數的一個別名,內部實現是隻讀指標
2:引用只能在初始化時被賦值,其他時候值不能被改變,指標的值可以在任何時候被改變
3:引用不能為NULL,指標可以為NULL
4:引用變數記憶體單元儲存的是被引用變數的地址
5:“sizeof 引用" = 指向變數的大小 , "sizeof 指標"= 指標本身的大小
6:引用可以取地址操作,返回的是被引用變數本身所在的記憶體單元地址
7:引用使用在原始碼級相當於普通的變數一樣使用,做函式引數時,內部傳遞的實際是變數地址
3.C++中有了malloc / free , 為什麼還需要 new / delete
1,malloc與free是C++/C語言的標準庫函式,new/delete是C++的運算子。它們都可用於申請動態記憶體和釋放記憶體。
2,對於非內部資料型別的物件而言,光用maloc/free無法滿足動態物件的要求。物件在建立的同時要自動執行建構函式,物件在消亡之前要自動執行解構函式。
由於malloc/free是庫函式而不是運算子,不在編譯器控制權限之內,不能夠把執行建構函式和解構函式的任務強加於malloc/free。
3,因此C++語言需要一個能完成動態記憶體分配和初始化工作的運算子new,以一個能完成清理與釋放記憶體工作的運算子delete。注意new/delete不是庫函式。
4.編寫類String 的建構函式,解構函式,拷貝建構函式和賦值函式
5 多型的實現
6. 單鏈表的逆置
7、一個由c/C++編譯的程式佔用的記憶體分為以下幾個部分
1、棧區(stack)― 由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。
2、堆區(heap) ― 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由OS回收 。
注意它與資料結構中的堆是兩回事,分配方式倒是類似於連結串列,呵呵。
3、全域性區(靜態區)(static)―,全域性變數和靜態變數的儲存是放在一塊的,
初始化的全域性變數和靜態變數在一塊區域, 未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。 - 程式結束後有系統釋放
4、文字常量區 ―常量字串就是放在這裡的。 程式結束後由系統釋放
5、程式程式碼區―存放函式體的二進位制程式碼。
4 不呼叫C/C++ 的字串庫函式,編寫strcpy
char * strcpy(char * strDest,const char * strSrc)
{
if ((strDest==NULL)||strSrc==NULL))
return NULL;
char * strDestCopy=strDest;
while ((*strDest++=*strSrc++)!='\0');
*strDest = '\0';
return strDestCopy;
}
1. 函式體內 static 變數的作用範圍為該函式體,不同於 auto 變數, 該變數的記憶體只被分配一次,因此其值在下次呼叫時仍維持上次的值
2. 在模組內的 static 全域性變數可以被模組內所有函式訪問,但不能被模組外其他函式訪問
3. 在模組內的static 函式只可被這一模組內的其他函式呼叫,這個函式的使用範圍被限制在宣告它的模組內
4. 在類的static 成員變數屬於整個類所擁有,對類的所以物件只有一份拷貝
5. 在類中的 static 成員函式屬於整個類所擁有,這個函式不接收 this 指標,因而只能訪問類的 static 成員變數
6. 在c++程式中呼叫被C編譯器編譯後的函式,為什麼要加extern“C”
C++語言支援函式過載,C語言不支援函式過載,函式被C++編譯器編譯後在庫中的名字與C語言的不同,
假設某個函式原型為:
void foo(int x, inty);
該函式被C編譯器編譯後在庫中的名字為: _foo
而C++編譯器則會產生像: _foo_int_int 之類的名字。
為了解決此類名字匹配的問題,C++提供了C連結交換指定符號 extern "C"。
7. 標頭檔案種的ifndef/define/endif 是幹什麼用的
防止標頭檔案被重複包含
8. 執行緒和程序的聯絡和區別
http://blog.csdn.NET/wolenski/article/details/7969908
9. 執行緒有哪幾種狀態
http://blog.csdn.Net/wolenski/article/details/7969908
10 執行緒同步和執行緒互斥的區別
http://blog.csdn.net/wolenski/article/details/7969908
11 執行緒同步的方式
Linux: 互斥鎖、條件變數和訊號量
http://blog.csdn.net/zsf8701/article/details/7844316
12. 網路七層
13 TCP和UDP有什麼區別
TCP---傳輸控制協議,提供的是面向連線、可靠的位元組流服務。
當客戶和伺服器彼此交換資料前,必須先在雙方之間建立一個TCP連線,之後才能傳輸資料。
TCP提供超時重發,丟棄重複資料,檢驗資料,流量控制等功能,保證資料能從一端傳到另一端。
UDP---使用者資料報協議,是一個簡單的面向資料報的運輸層協議。
UDP不提供可靠性,它只是把應用程式傳給IP層的資料報傳送出去,但是並不能保證它們能到達目的地。
由於UDP在傳輸資料報前不用在客戶和伺服器之間建立一個連線,且沒有超時重發等機制,故而傳輸速度很快
14編寫socket套接字的步驟
15. TCP三次握手和四次揮手, 以及各個狀態的作用
http://hi.baidu.com/suxinpingtao51/item/be5f71b3a907dbef4ec7fd0e?qq-pf-to=pcqq.c2c
16. HTTP協議
http(超文字傳輸協議)是一個基於請求與響應模式的、無狀態的、應用層的協議,常基於TCP的連線方式,
HTTP1.1版本中給出一種持續連線的機制,絕大多數的Web開發,都是構建在HTTP協議之上的Web應用。
TCP 和 HTTP區別: http://blog.csdn.net/lemonxuexue/article/details/4485877
17 使用過的 shell 命令
cp , mv , rm , mkdir , touch , pwd , cd , ls , top , cat , tail , less , df , du , man , find , kill , sudo , cat
18. 使用過的 vim 命令
wq!, dd , dw , yy , p , i , %s/old/new/g , /abc 向後搜尋字串abc , ?abc向前搜尋字串abc
19. 使用過的 gdb 命令
http://blog.csdn.net/dadalan/article/details/3758025
20. 常見演算法
快速排序、堆排序和歸併排序
堆排序 : http://blog.csdn.net/xiaoxiaoxuewen/article/details/7570621
快速排序、歸併排序: http://blog.csdn.net/morewindows/article/details/6684558
穩定性分析 http://baike.baidu.com/link?url=ueoZ3sNIOvMNPrdCKbd8mhfebC85B4nRc-7hPEJWi-hFo5ROyWH2Pxs9RtvLFRJL
21C庫函式實現
22 靜態連結串列和動態連結串列的區別
http://blog.csdn.net/toonny1985/article/details/4868786
23 大併發( epoll )
優點:
http://blog.csdn.net/sunyurun/article/details/8194979
例項:
http://www.cnblogs.com/ggjucheng/archive/2012/01/17/2324974.htm
24. 海量資料處理的知識點,(hash表, hash統計)
hash表: http://hi.baidu.com/05104106/item/62736054402852c09e26679b
海量資料處理方法: http://blog.csdn.net/v_july_v/article/details/7382693
25. 什麼時候要用虛解構函式
通過基類的指標來刪除派生類的物件時,基類的解構函式應該是虛的。否則其刪除效果將無法實現。
一般情況下,這樣的刪除只能夠刪除基類物件,而不能刪除子類物件,形成了刪除一半形象,從而千萬記憶體洩漏。
原因:
在公有繼承中,基類對派生類及其物件的操作,只能影響到那些從基類繼承下來的成員。
如果想要用基類對非繼承成員進行操作,則要把基類的這個操作(函式)定義為虛擬函式。
那麼,解構函式自然也應該如此:如果它想析構子類中的重新定義或新的成員及物件,當然也應該宣告為虛的。
注意:
如果不需要基類對派生類及物件進行操作,則不能定義虛擬函式(包括虛解構函式),因為這樣會增加記憶體開銷。
26. c++怎樣讓返回物件的函式不呼叫拷貝建構函式
拷貝建構函式前加 “explicit” 關鍵字
27 孤兒程序和殭屍程序
http://www.cnblogs.com/Anker/p/3271773.html
下面是經典20道
問1:請用簡單的語言告訴我C++ 是什麼?
答:C++是在C語言的基礎上開發的一種面向物件程式語言,應用廣泛。C++支援多種程式設計正規化 --面向物件程式設計、泛型程式設計和過程化程式設計。 其程式設計領域眾廣,常用於系統開發,引擎開發等應用領域,是最受廣大程式設計師受用的最強大程式語言之一,支援類:類、封裝、過載等特性!
問2:C和C++的區別?
答:c++在c的基礎上增添類,C是一個結構化語言,它的重點在於演算法和資料結構。C程式的設計首要考慮的是如何通過一個過程,對輸入(或環境條件)進行運算處理得到輸出(或實現過程(事務)控制),而對於C++,首要考慮的是如何構造一個物件模型,讓這個模型能夠契合與之對應的問題域,這樣就可以通過獲取物件的狀態資訊得到輸出或實現過程(事務)控制。
問3:什麼是面向物件(OOP)?
答:面向物件是一種對現實世界理解和抽象的方法、思想,通過將需求要素轉化為物件進行問題處理的一種思想。
問4:什麼是多型?
答:多型是指相同的操作或函式、過程可作用於多種型別的物件上並獲得不同的結果。不同的物件,收到同一訊息可以產生不同的結果,這種現象稱為多型。
問5:設計模式懂嘛,簡單舉個例子?
答:設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類編目的、程式碼設計經驗的總結。
比如單例模式,保證一個類僅有一個例項,並提供一個訪問它的全域性訪問點。
適用於:當類只能有一個例項而且客戶可以從一個眾所周知的訪問點訪問它時;當這個唯一例項應該是通過子類化可擴充套件的,並且客戶應該無需更改程式碼就能使用一個擴充套件的例項時。
比如工廠模式,定義一個用於建立物件的介面,讓子類決定例項化哪一個類。Factory Method 使一個類的例項化延遲到其子類。
適用於:當一個類不知道它所必須建立的物件的類的時候;當一個類希望由它的子類來指定它所建立的物件的時候;當類將建立物件的職責委託給多個幫助子類中的某一個,並且你希望將哪一個幫助子類是代理者這一資訊區域性化的時候。
問6:STL庫用過嗎?常見的STL容器有哪些?演算法用過哪幾個?
答:STL包括兩部分內容:容器和演算法。(重要的還有融合這二者的迭代器)容器,即存放資料的地方。比如array等。在STL中,容器分為兩類:序列式容器和關聯式容器。
序列式容器,其中的元素不一定有序,但都可以被排序。如:vector、list、deque、stack、queue、heap、priority_queue、slist;
關聯式容器,內部結構基本上是一顆平衡二叉樹。所謂關聯,指每個元素都有一個鍵值和一個實值,元素按照一定的規則存放。如:RB-tree、set、map、multiset、multimap、hashtable、hash_set、hash_map、hash_multiset、hash_multimap。
下面各選取一個作為說明。
vector:它是一個動態分配儲存空間的容器。區別於c++中的array,array分配的空間是靜態的,分配之後不能被改變,而vector會自動重分配(擴充套件)空間。
set:其內部元素會根據元素的鍵值自動被排序。區別於map,它的鍵值就是實值,而map可以同時擁有不同的鍵值和實值。
演算法,如排序,複製……以及個容器特定的演算法。這點不用過多介紹,主要看下面迭代器的內容。
迭代器是STL的精髓,我們這樣描述它:迭代器提供了一種方法,使它能夠按照順序訪問某個容器所含的各個元素,但無需暴露該容器的內部結構。它將容器和演算法分開,好讓這二者獨立設計。
問7:資料結構會嗎?專案開發過程中主要用到那些?
答:資料結構中主要會用到陣列,連結串列,樹(較少),也會用到棧和佇列的思想。
問8:const知道嗎?解釋其作用。
答:
1.const 修飾類的成員變數,表示成員常量,不能被修改。
2.const修飾函式承諾在本函式內部不會修改類內的資料成員,不會呼叫其它非 const 成員函式。
3.如果 const 構成函式過載,const 物件只能呼叫 const 函式,非 const 物件優先呼叫非 const 函式。
4.const 函式只能呼叫 const 函式。非 const 函式可以呼叫 const 函式。
5.類體外定義的 const 成員函式,在定義和宣告處都需要 const 修飾符。。
問9:類的static變數在什麼時候初始化?函式的static變數在什麼時候初始化?
答:類的靜態成員變數在類例項化之前就已經存在了,並且分配了記憶體。函式的static變數在執行此函式時進行初始化。
問10:堆和棧的區別?堆和棧的生命週期?
答:
一、堆疊空間分配區別:
1、棧(作業系統):由作業系統自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧;
2、堆(作業系統): 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由OS回收,分配方式倒是類似於連結串列。
二、堆疊快取方式區別:
1、棧使用的是一級快取, 他們通常都是被呼叫時處於儲存空間中,呼叫完畢立即釋放;
2、堆是存放在二級快取中,生命週期由虛擬機器的垃圾回收演算法來決定(並不是一旦成為孤兒物件就能被回收)。所以呼叫這些物件的速度要相對來得低一些。
三、堆疊資料結構區別:
堆(資料結構):堆可以被看成是一棵樹,如:堆排序;
棧(資料結構):一種先進後出的資料結構。
問11:C和C++的區別?
答:C++在C的基礎上增添類
C是一個結構化語言,它的重點在於演算法和資料結構。
C程式的設計首要考慮的是如何通過一個過程,對輸入(或環境條件)進行運算處理得到輸出(或實現過程(事務)控制),而對於C++,首要考慮的是如何構造一個物件模型,讓這個模型能夠契合與之對應的問題域,這樣就可以通過獲取物件的狀態資訊得到輸出或實現過程(事務)控制。
問12:解釋下封裝、繼承和多型?
一、封裝:
封裝是實現面向物件程式設計的第一步,封裝就是將資料或函式等集合在一個個的單元中(我們稱之為類)。
封裝的意義在於保護或者防止程式碼(資料)被我們無意中破壞。
二、繼承:
繼承主要實現重用程式碼,節省開發時間。
子類可以繼承父類的一些東西。
三、多型
多型:同一操作作用於不同的物件,可以有不同的解釋,產生不同的執行結果。在執行時,可以通過指向基類的指標,來呼叫實現派生類中的方法。
問13:指標和引用的區別?
答:
1. 指標是一個變數,只不過這個變數儲存的是一個地址,指向記憶體的一個儲存單元;而引用僅是個別名;
2. 引用使用時無需解引用(*),指標需要解引用;
3. 引用只能在定義時被初始化一次,之後不可變;指標可變;
4. 引用沒有 const,指標有 const;
5. 引用不能為空,指標可以為空;
6. “sizeof 引用”得到的是所指向的變數(物件)的大小,而“sizeof 指標”得到的是指標本身的大小;
7. 指標和引用的自增(++)運算意義不一樣;
8. 指標可以有多級,但是引用只能是一級(int **p;合法 而 int &&a是不合法的)
9.從記憶體分配上看:程式為指標變數分配記憶體區域,而引用不需要分配記憶體區域。
問14:什麼是記憶體洩漏?面對記憶體洩漏和指標越界,你有哪些方法?你通常採用哪些方法來避免和減少這類錯誤?
答:用動態儲存分配函式動態開闢的空間,在使用完畢後未釋放,結果導致一直佔據該記憶體單元即為記憶體洩露。
使用的時候要記得指標的長度。
malloc的時候得確定在那裡free.
對指標賦值的時候應該注意被賦值指標需要不需要釋放.
動態分配記憶體的指標最好不要再次賦值.
問15:常用的排序演算法有哪些?簡單描述幾個排序演算法的優缺點?
答:選擇、冒泡、快速、**、希爾、歸併、堆排等。
1.快排:是氣泡排序的一種改進。
優點:快,資料移動少
缺點:穩定性不足
2.歸併:分治法排序,穩定的排序演算法,一般用於對總體無序,但區域性有序的數列。
優點:效率高O(n),穩定
缺點:比較佔用記憶體
問16:new和malloc的區別?
答:
1、malloc與free是C++/C語言的標準庫函式,new/delete是C++的運算子。它們都可用於申請動態記憶體和釋放記憶體。
2、對於非內部資料型別的物件而言,光用maloc/free無法滿足動態物件的要求。物件在建立的同時要自動執行建構函式,物件在消亡之前要自動執行解構函式。
3、由於malloc/free是庫函式而不是運算子,不在編譯器控制權限之內,不能夠把執行建構函式和解構函式的任務強加於malloc/free。因此C++語言需要一個能完成動態記憶體分配和初始化工作的運算子new,以一個能完成清理與釋放記憶體工作的運算子delete。注意new/delete不是庫函式。
4、C++程式經常要呼叫C函式,而C程式只能用malloc/free管理動態記憶體。
5、new可以認為是malloc加建構函式的執行。new出來的指標是直接帶型別資訊的。而malloc返回的都是void指標。
問17:TCP和UDP通訊的差別?什麼是IOCP?
答:
1.TCP面向連線, UDP面向無連線的
2.TCP有保障的,UDP傳輸無保障的
3.TCP是效率低的,UDP效率高的
4.TCP是基於流的,UDP基於資料報文
5.TCP傳輸重要資料,UDP傳輸不重要的資料
IOCP全稱I/O Completion Port,中文譯為I/O完成埠。
IOCP是一個非同步I/O的API,它可以高效地將I/O事件通知給應用程式。
與使用select()或是其它非同步方法不同的是,一個套接字[socket]與一個完成埠關聯了起來,然後就可繼續進行正常的Winsock操作了。然而,當一個事件發生的時候,此完成埠就將被作業系統加入一個佇列中。然後應用程式可以對核心層進行查詢以得到此完成埠。
問18:同步IO和非同步IO的區別?
答:
A. 同步
所謂同步,就是在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。
按照這個定義,其實絕大多數函式都是同步呼叫(例如sin isdigit等)。
但是一般而言,我們在說同步、非同步的時候,特指那些需要其他部件協作或者需要一定時間完成的任務。
最常見的例子就是 SendMessage。
該函式傳送一個訊息給某個視窗,在對方處理完訊息之前,這個函式不返回。
當對方處理完畢以後,該函式才把訊息處理函式所返回的值返回給呼叫者。
B. 非同步
非同步的概念和同步相對。
當一個非同步過程呼叫發出後,呼叫者不會立刻得到結果。
實際處理這個呼叫的部件是在呼叫發出後,通過狀態、通知來通知呼叫者,或通過回撥函式處理這個呼叫。
問19:解釋C++中靜態函式和靜態變數?
答:
(1)類靜態資料成員在編譯時建立並初始化:在該類的任何物件建立之前就存在,不屬於任何物件,而非靜態類成員變數則是屬於物件所有的。類靜態資料成員只有一個拷貝,為所有此類的物件所共享。
(2)類靜態成員函式屬於整個類,不屬於某個物件,由該類所有物件共享。
1、static 成員變數實現了同類物件間資訊共享。
2、static 成員類外儲存,求類大小,並不包含在內。
3、static 成員是名稱空間屬於類的全域性變數,儲存在 data 區的rw段。
4、static 成員只能類外初始化。
5、可以通過類名訪問(無物件生成時亦可),也可以通過物件訪問。
1、靜態成員函式的意義,不在於資訊共享,資料溝通,而在於管理靜態資料成員,完成對靜態資料成員的封裝。
2、靜態成員函式只能訪問靜態資料成員。原因:非靜態成員函式,在呼叫時 this指標時被當作引數傳進。而靜態成員函式屬於類,而不屬於物件,沒有 this 指標。
問20:說下你對記憶體的瞭解?
答:
1.棧 - 由編譯器自動分配釋放
2.堆 - 一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由OS回收
3.全域性區(靜態區),全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域,未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。- 程式結束釋放
4.另外還有一個專門放常量的地方。- 程式結束釋放
5 程式程式碼區,存放2進位制程式碼。
在函式體中定義的變數通常是在棧上,用malloc, calloc, realloc等分配記憶體的函式分配得到的就是在堆上。在所有函式體外定義的是全域性量,加了static修飾符後不管在哪裡都存放在全域性區(靜態區),在所有函式體外定義的static變量表示在該檔案中有效,不能extern到別的檔案用,在函式體內定義的static表示只在該函式體內有效。另外,函式中的"adgfdf"這樣的字串存放在常量區。