C、C++、數(shù)據(jù)結(jié)構(gòu)
1、編譯系統(tǒng)的四個步驟: 預(yù)處理,編譯,匯編,鏈接
2、整型和長整型的區(qū)別?
早期的計算機(jī),16編譯器, 整型是16位,長整型是32位的。
從C99規(guī)定開始,整型和長整型都是32位,也就是我們sizeof得出的4個字節(jié)
3、for(;;)和while(1)無限循環(huán)的區(qū)別:
for(;;)在c語言中指令較少,也能夠節(jié)省內(nèi)存,沒有判斷跳轉(zhuǎn),是比while(1)更好的無限循環(huán)
4、指針和數(shù)組的組合
int a; //整型數(shù)a
int *a; //整型指針a
int **a; //指向指針的指針,a指針返回一個整型
int a[10]; //數(shù)組a里有10個整型
int *a[10]; //數(shù)組a里面10個 指針,指針指向整型
int (*a)[10]; //指針a指向10個整型數(shù)組
int *a(int); //指針a指向函數(shù),函數(shù)參數(shù)是整型,返回值是整型
int (*a[10])(int); //數(shù)組a里面10個 指針,指針指向函數(shù),函數(shù)參數(shù)是整型,返回值是整型
5、關(guān)鍵字static的作用
- 函數(shù)體內(nèi) static 變量的作用范圍為該函數(shù)體,不同于 auto 變量, 該變量的內(nèi)存只被分配一次,因此其值在下次調(diào)用時仍維持上次的值
- 在模塊內(nèi)的 static 全局變量可以被模塊內(nèi)所有函數(shù)訪問,但不能被模塊外其他函數(shù)訪問
- 在模塊內(nèi)的static 函數(shù)只可被這一模塊內(nèi)的其他函數(shù)調(diào)用,這個函數(shù)的使用范圍被限制在聲明它的模塊內(nèi)
- 在類的static 成員變量屬于整個類所擁有,對類的所以對象只有一份拷貝
- 在類中的 static 成員函數(shù)屬于整個類所擁有,這個函數(shù)不接收 this 指針,因而只能訪問類的 static 成員變量。
6、const的作用?
1)可以定義const常量量,具有不可變性。
2)便于進(jìn)行類型檢查,使編譯器對處理內(nèi)容有更好了解,消除一些隱患。
3)可以避免意義模糊的數(shù)字出現(xiàn),同樣可以方便進(jìn)行參數(shù)的調(diào)整和修改可以保護(hù)被修飾的東西,防止意外的修改。
4)為函數(shù)重載提供一個參數(shù)。
5)可以節(jié)省空間,避免不必要的內(nèi)存分配。
6)編譯器通常不為普通的const常量分配內(nèi)存,將他保存在符號表,沒有存儲和讀取的操作,效率變高。
7、如果一個函數(shù)沒有顯式地聲明返回值,那么默認(rèn)的返回值就是int型的
在c語言中,如果一個函數(shù)沒有顯式地說明參數(shù)是void,那么是可以使用參數(shù)的進(jìn)行調(diào)用的
在C++這樣是不可以的
8、大小端問題值得注意:跟處理器有關(guān),可以使用程序判定
#include <iostream>
using namespace std;
union Test
{
int a;
char b;
};
int main()
{
Test t;
t.a = 1;
if (t.b == 1)
cout << "小端" << endl;
else
cout << "大端" << endl;
return 0;
}
9、enum是在編譯階段確定其值的
10、const修飾的只讀變量不能用來作為定義數(shù)組的維數(shù),也不能放在case關(guān)鍵字后面
11、strlen和sizeof的區(qū)別?
1)strlen是一個函數(shù),sizeof是一個運算符。
2)sizeof獲得保證能容納實現(xiàn)所建立的最大對象的字節(jié)大小,不能用來返回動態(tài)分配的內(nèi)存空間的大小。
3)strlen要在運行時才能計算,參數(shù)必須是字符型指針,返回字符串的長度。
12、指針和引用的區(qū)別
1.引用是變量的一個別名,內(nèi)部實現(xiàn)是只讀指針
2.引用只能在初始化時被賦值,其他時候值不能被改變,指針的值可以在任何時候被改變
3.引用不能為NULL,指針可以為NULL
4.引用變量內(nèi)存單元保存的是被引用變量的地址
5.“sizeof 引用" = 指向變量的大小 , "sizeof 指針"= 指針本身的大小
6.引用可以取地址操作,返回的是被引用變量本身所在的內(nèi)存單元地址
7.引用使用在源代碼級相當(dāng)于普通的變量一樣使用,做函數(shù)參數(shù)時,內(nèi)部傳遞的實際是變量地址
13、C++中有了malloc / free , 為什么還需要 new / delete
- malloc與free是C++/C語言的標(biāo)準(zhǔn)庫函數(shù),new/delete是C++的運算符。它們都可用于申請動態(tài)內(nèi)存和釋放內(nèi)存。
- 對于非內(nèi)部數(shù)據(jù)類型的對象而言,光用maloc/free無法滿足動態(tài)對象的要求。對象在創(chuàng)建的同時要自動執(zhí)行構(gòu)造函數(shù),對象在消亡之前要自動執(zhí)行析構(gòu)函數(shù)。由于malloc/free是庫函數(shù)而不是運算符,不在編譯器控制權(quán)限之內(nèi),不能夠把執(zhí)行構(gòu)造函數(shù)和析構(gòu)函數(shù)的任務(wù)強(qiáng)加于malloc/free。
- 因此C++語言需要一個能完成動態(tài)內(nèi)存分配和初始化工作的運算符new,以一個能完成清理與釋放內(nèi)存工作的運算符delete。注意new/delete不是庫函數(shù)。
14、堆和棧的區(qū)別
- 棧區(qū)(stack): 由編譯器自動分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等,操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
- 堆區(qū)(heap) : 一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時可能由OS回收 。注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,作方式類似于數(shù)據(jù)結(jié)構(gòu)中的鏈表。
15、不調(diào)用C/C++ 的字符串庫函數(shù),編寫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;
}
16、關(guān)鍵字static的作用
1.函數(shù)體內(nèi) static 變量的作用范圍為該函數(shù)體,不同于 auto 變量, 該變量的內(nèi)存只被分配一次,因此其值在下次調(diào)用時仍維持上次的值
2.在模塊內(nèi)的 static 全局變量可以被模塊內(nèi)所有函數(shù)訪問,但不能被模塊外其他函數(shù)訪問
3.在模塊內(nèi)的static 函數(shù)只可被這一模塊內(nèi)的其他函數(shù)調(diào)用,這個函數(shù)的使用范圍被限制在聲明它的模塊內(nèi)
4.在類的static 成員變量屬于整個類所擁有,對類的所以對象只有一份拷貝
5.在類中的 static 成員函數(shù)屬于整個類所擁有,這個函數(shù)不接收 this 指針,因而只能訪問類的 static 成員變量
17、什么時候要用虛析構(gòu)函數(shù)
通過基類的指針來刪除派生類的對象時,基類的析構(gòu)函數(shù)應(yīng)該是虛的。否則其刪除效果將無法實現(xiàn)。一般情況下,這樣的刪除只能夠刪除基類對象,而不能刪除子類對象,造成內(nèi)存泄漏。
原因:在公有繼承中,基類對派生類及其對象的操作,只能影響到那些從基類繼承下來的成員。如果想要用基類對非繼承成員進(jìn)行操作,則要把基類的這個操作(函數(shù))定義為虛函數(shù)。那么,析構(gòu)函數(shù)自然也應(yīng)該如此:如果它想析構(gòu)子類中的重新定義或新的成員及對象,當(dāng)然也應(yīng)該聲明為虛的。
注意:如果不需要基類對派生類及對象進(jìn)行操作,則不能定義虛函數(shù)(包括虛析構(gòu)函數(shù)),因為這樣會增加內(nèi)存開銷。
18、C++怎樣讓返回對象的函數(shù)不調(diào)用拷貝構(gòu)造函數(shù)
拷貝構(gòu)造函數(shù)前加 “explicit” 關(guān)鍵字
19、請用簡單的語言告訴我C++ 是什么?
C++是在C語言的基礎(chǔ)上開發(fā)的一種面向?qū)ο缶幊陶Z言,應(yīng)用廣泛。C++支持多種編程范式 --面向?qū)ο缶幊獭⒎盒途幊毯瓦^程化編程。 其編程領(lǐng)域眾廣,常用于系統(tǒng)開發(fā),引擎開發(fā)等應(yīng)用領(lǐng)域。
20、C和C++的區(qū)別?
C++在c的基礎(chǔ)上增添類,C是一個結(jié)構(gòu)化語言,它的重點在于算法和數(shù)據(jù)結(jié)構(gòu)。C程序的設(shè)計首要考慮的是如何通過一個過程,對輸入(或環(huán)境條件)進(jìn)行運算處理得到輸出(或?qū)崿F(xiàn)過程(事務(wù))控制),而對于C++,首要考慮的是如何構(gòu)造一個對象模型,讓這個模型能夠契合與之對應(yīng)的問題域,這樣就可以通過獲取對象的狀態(tài)信息得到輸出或?qū)崿F(xiàn)過程(事務(wù))控制。
21、什么是多態(tài)?
多態(tài)是指相同的操作或函數(shù)、過程可作用于多種類型的對象上并獲得不同的結(jié)果。不同的對象,收到同一消息可以產(chǎn)生不同的結(jié)果,這種現(xiàn)象稱為多態(tài)。
22、類的static變量在什么時候初始化?函數(shù)的static變量在什么時候初始化?
類的靜態(tài)成員變量在類實例化之前就已經(jīng)存在了,并且分配了內(nèi)存。函數(shù)的static變量在執(zhí)行此函數(shù)時進(jìn)行初始化。
23、解釋下封裝、繼承和多態(tài)?
封裝:封裝是實現(xiàn)面向?qū)ο蟪绦蛟O(shè)計的第一步,封裝就是將數(shù)據(jù)或函數(shù)等集合在一個個的單元中(我們稱之為類)。封裝的意義在于保護(hù)或者防止代碼(數(shù)據(jù))被我們無意中破壞。
繼承:繼承主要實現(xiàn)重用代碼,節(jié)省開發(fā)時間。子類可以繼承父類的一些東西。
多態(tài):同一操作作用于不同的對象,可以有不同的解釋,產(chǎn)生不同的執(zhí)行結(jié)果。在運行時,可以通過指向基類的指針,來調(diào)用實現(xiàn)派生類中的方法。
24、什么是內(nèi)存泄漏?面對內(nèi)存泄漏和指針越界,你有哪些方法?你通常采用哪些方法來避免和減少這類錯誤?
用動態(tài)存儲分配函數(shù)動態(tài)開辟的空間,在使用完畢后未釋放,結(jié)果導(dǎo)致一直占據(jù)該內(nèi)存單元即為內(nèi)存泄露。
使用的時候要記得指針的長度。malloc的時候得確定在那里free.對指針賦值的時候應(yīng)該注意被賦值指針需要不需要釋放.動態(tài)分配內(nèi)存的指針最好不要再次賦值.
25、常用的排序算法有哪些?簡單描述幾個排序算法的優(yōu)缺點?
選擇、冒泡、快速、希爾、歸并、堆排等。
1.快排:是冒泡排序的一種改進(jìn)。
優(yōu)點:快,數(shù)據(jù)移動少
缺點:穩(wěn)定性不足
2.歸并:分治法排序,穩(wěn)定的排序算法,一般用于對總體無序,但局部有序的數(shù)列。
優(yōu)點:效率高O(n),穩(wěn)定
缺點:比較占用內(nèi)存
26、解釋C++中靜態(tài)函數(shù)和靜態(tài)變量?
- 類靜態(tài)數(shù)據(jù)成員在編譯時創(chuàng)建并初始化:在該類的任何對象建立之前就存在,不屬于任何對象,而非靜態(tài)類成員變量則是屬于對象所有的。類靜態(tài)數(shù)據(jù)成員只有一個拷貝,為所有此類的對象所共享。
- 類靜態(tài)成員函數(shù)屬于整個類,不屬于某個對象,由該類所有對象共享。
- 靜態(tài)成員函數(shù)的意義,不在于信息共享,數(shù)據(jù)溝通,而在于管理靜態(tài)數(shù)據(jù)成員,完成對靜態(tài)數(shù)據(jù)成員的封裝。
- 靜態(tài)成員函數(shù)只能訪問靜態(tài)數(shù)據(jù)成員。原因:非靜態(tài)成員函數(shù),在調(diào)用時 this指針時被當(dāng)作參數(shù)傳進(jìn)。而靜態(tài)成員函數(shù)屬于類,而不屬于對象,沒有 this 指針。
27、

28、重載 ( overload) 和覆蓋 (override 重寫)的區(qū)別?
重載:是指允許存在多個同名函數(shù),而這些函數(shù)的參數(shù)表不同(或許參數(shù)個數(shù)不同,或許參數(shù)類型不同,或許兩者都不同)。
重寫:是指子類重新定義父類虛函數(shù)的方法。
29、多態(tài)的作用?
主要是兩個:
- 隱藏實現(xiàn)細(xì)節(jié),使得代碼能夠模塊化;擴(kuò)展代碼模塊,實現(xiàn)代碼重用;
- 接口重用:為了類在繼承和派生的時候 ,保證使用家族中任一類的實例的某一屬性時的正確調(diào)用 。
30、類成員函數(shù)的重載、覆蓋和遮蔽區(qū)別?
a. 成員函數(shù)被重載的特征:
( 1 )相同的范圍(在同一個類中);
( 2 )函數(shù)名字相同;
( 3 )參數(shù)不同;
( 4 ) virtual 關(guān)鍵字可有可無。
b. 覆蓋是指派生類函數(shù)覆蓋基類函數(shù),特征是:
( 1 )不同的范圍(分別位于派生類與基類);
( 2 )函數(shù)名字相同;
( 3 )參數(shù)相同;
( 4 )基類函數(shù)必須有 virtual 關(guān)鍵字。
c. 遮蔽是指派生類的函數(shù)屏蔽了與其同名的基類函數(shù),規(guī)則如下:
( 1 )如果派生類的函數(shù)與基類的函數(shù)同名,但是參數(shù)不同。此時,不論有無 virtual 關(guān)鍵字,基類的函數(shù)將被隱藏(注意別與重載混淆)。
( 2 )如果派生類的函數(shù)與基類的函數(shù)同名,并且參數(shù)也相同,但是基類函數(shù)沒有 virtual 關(guān)鍵字。此時,基類的函數(shù)被隱藏(注意別與覆蓋混淆)
31、什么是動態(tài)特性?
在絕大多數(shù)情況下, 程序的功能是在編譯的時候就確定下來的, 我們稱之為靜態(tài)特性。 反之, 如果程序的功能是在運行時刻才能確定下來的, 則稱之為動態(tài)特性。C++中, 虛函數(shù),抽象基類, 動態(tài)綁定和多態(tài)構(gòu)成了出色的動態(tài)特性。
32、在C++ 程序中調(diào)用被 C 編譯器編譯后的函數(shù),為什么要加 extern “C”聲明?
函數(shù)和變量被C++編譯后在符號庫中的名字與C語言的不同,被extern “C”修飾的變量和函數(shù)是按照C語言方式編譯和連接的。由于編譯后的名字不同,C++程序不能直接調(diào)用C 函數(shù)。C++提供了一個C 連接交換指定符號extern“C”來解決這個問題。
33、內(nèi)聯(lián)函數(shù)INline和宏定義一起使用的區(qū)別。
內(nèi)聯(lián)函數(shù)是在編譯的時候已經(jīng)做好將對應(yīng)的函數(shù)代碼替換嵌入到對應(yīng)的位置,適用于代碼較少的函數(shù)。 宏定義是簡單的替換變量,如果定義的是有參數(shù)的函數(shù)形式,參數(shù)不做類型校驗。
34、一個空類默認(rèn)存在的成員函數(shù)有哪些?
默認(rèn)構(gòu)造函數(shù)、默認(rèn)拷貝構(gòu)造函數(shù)、默認(rèn)析構(gòu)函數(shù)、默認(rèn)賦值運算符 這四個是我們通常大都知道的。但是除了這四個,還有兩個,那就是取址運算符和 取址運算符 const
即總共有六個函數(shù)。
class Empty
{
public:
Empty(); // 缺省構(gòu)造函數(shù)
Empty( const Empty& ); // 拷貝構(gòu)造函數(shù)
~Empty(); // 析構(gòu)函數(shù)
Empty& operator=( const Empty& ); // 賦值運算符
Empty* operator&(); // 取址運算符
const Empty* operator&() const; // 取址運算符 const
};
35、C++中哪些函數(shù)不能被聲明為虛函數(shù)?
普通函數(shù)(非成員函數(shù)),構(gòu)造函數(shù),內(nèi)聯(lián)成員函數(shù)、靜態(tài)成員函數(shù)、友元函數(shù)。
(1)虛函數(shù)用于基類和派生類,普通函數(shù)所以不能
(2)構(gòu)造函數(shù)不能是因為虛函數(shù)采用的是虛調(diào)用的方法,
(3)內(nèi)聯(lián)成員函數(shù)的實質(zhì)是在調(diào)用的地方直接將代碼擴(kuò)展開
(4)繼承時,靜態(tài)成員函數(shù)不能被繼承的,它只屬于一個類,因為也不存在動態(tài)聯(lián)編
(5)友元函數(shù)不是類的成員函數(shù),因此也不能被繼承
36、類的靜態(tài)成員和非靜態(tài)成員有何區(qū)別?
類的靜態(tài)成員每個類只有一個,靜態(tài)成員為所有類的實例對象共享,靜態(tài)成員有靜態(tài)成員變量和靜態(tài)成員函數(shù),靜態(tài)成員變量使用前必須初始化,靜態(tài)成員變量可以被靜態(tài)成員函數(shù)和非靜態(tài)成員函數(shù)訪問,而靜態(tài)成員函數(shù)只能訪問靜態(tài)成員變量,因為靜態(tài)成員函數(shù)屬于類,其沒有this指針。非靜態(tài)成員每個對象都有一個。
37、繼承的優(yōu)缺點。
類繼承是在編譯時刻靜態(tài)定義的,且可直接使用,類繼承可以較方便地改變父類的實現(xiàn)。但是類繼承也有一些不足之處。首先,因為繼承在編譯時刻就定義了,所以無法在運行時刻改變從父類繼承的實現(xiàn)。更糟的是,父類通常至少定義了子類的部分行為,父類的任何改變都可能影響子類的行為。如果繼承下來的實現(xiàn)不適合解決新的問題,則父類必須重寫或被其他更適合的類替換。這種依賴關(guān)系限制了靈活性并最終限制了復(fù)用性。
38、在什么時候需要使用“常引用”?
如果既要利用引用提高程序的效率,又要保護(hù)傳遞給函數(shù)的數(shù)據(jù)不在函數(shù)中被改變,就 應(yīng)使用常引用。常引用聲明方式:const 類型標(biāo)識符 &引用名=目標(biāo)變量名;
39、什么是淺拷貝?什么是深拷貝?
淺拷貝是指源對象與拷貝對象共用一份實體,僅僅是引用的變量不同(名稱不同)。對其中任何一個對象的改動都會影響另外一個對象。
深拷貝是指源對象與拷貝對象互相獨立,其中任何一個對象的改動都不會對另外一個對象造成影響。
一般來說,淺拷貝就是復(fù)制那個對象的指針。深拷貝就是復(fù)制了那個對象。
40、簡述多態(tài)實現(xiàn)的原理
編譯器發(fā)現(xiàn)一個類中有虛函數(shù),便會立即為此類生成虛函數(shù)表 vtable。虛函數(shù)表的各表項為指向?qū)?yīng)虛函數(shù)的指針。編譯器還會在此類中隱含插入一個指針vptr(對vc編譯器來說,它插在類的第一個位置上)指向虛函數(shù)表。調(diào)用此類的構(gòu)造函數(shù)時,在類的構(gòu)造函數(shù)中,編譯器會隱含執(zhí)行vptr與vtable的關(guān)聯(lián)代碼,將vptr指向?qū)?yīng)的vtable,將類與此類的vtable聯(lián)系了起來。另外在調(diào)用類的構(gòu)造函數(shù)時,指向基礎(chǔ)類的指針此時已經(jīng)變成指向具體的類的this指針,這樣依靠此this指針即可得到正確的vtable,。如此才能真正與函數(shù)體進(jìn)行連接,這就是動態(tài)聯(lián)編,實現(xiàn)多態(tài)的基本原理。
41、談?wù)勀銓γ嫦驅(qū)ο蟮恼J(rèn)識
解析:面向?qū)ο罂梢岳斫獬蓪Υ恳粋€問題,都是首先要確定這個問題由幾個部分組成,而每一個部分其實就是一個對象。然后再分別設(shè)計這些對象,最后得到整個程序。傳統(tǒng)的程序設(shè)計多是基于功能的思想來進(jìn)行考慮和設(shè)計的,而面向?qū)ο蟮某绦蛟O(shè)計則是基于對象的角度來考慮問題。這樣做能夠使得程序更加的簡潔清晰。
42、C++中為什么用模板類。
- 可用來創(chuàng)建動態(tài)增長和減小的數(shù)據(jù)結(jié)構(gòu)
- 它是類型無關(guān)的,因此具有很高的可復(fù)用性。
- 它在編譯時而不是運行時檢查數(shù)據(jù)類型,保證了類型安全
- 它是平臺無關(guān)的,可移植性
- 可用于基本數(shù)據(jù)類型
43 、函數(shù)模板與類模板有什么區(qū)別?
函數(shù)模板的實例化是由編譯程序在處理函數(shù)調(diào)用時自動完成的,而類模板的實例化
必須由程序員在程序中顯式地指定。
44、C++是不是類型安全的?
不是。兩個不同類型的指針之間可以強(qiáng)制轉(zhuǎn)換
45、流操作符重載為什么返回引用
在程序中,流操作符>>和<<經(jīng)常連續(xù)使用。因此這兩個操作符的返回值應(yīng)該是一個仍舊支持這兩個操作符的流引用。其他的數(shù)據(jù)類型都無法做到這一點。
注意:除了在賦值操作符和流操作符之外的其他的一些操作符中,如+、-、*、/等卻千萬不能返回引用。因為這四個操作符的對象都是右值,因此,它們必須構(gòu)造一個對象作為返回值。
46、多態(tài), 虛函數(shù), 純虛函數(shù)
多態(tài):不同對象接收相同的消息產(chǎn)生不同的動作。多態(tài)包括 編譯時多態(tài)和 運行時多態(tài)
運行時多態(tài)是:通過繼承和虛函數(shù)來體現(xiàn)的。 編譯時多態(tài):運算符重載上。
虛函數(shù): 在基類中用virtual的成員函數(shù)。允許在派生類中對基類的虛函數(shù)重新定義。 基類的虛函數(shù)可以有函數(shù)體,基類也可以實例化。 虛函數(shù)要有函數(shù)體,否則編譯過不去。 虛函數(shù)在子類中可以不覆蓋。 構(gòu)造函數(shù)不能是虛函數(shù)。
純虛函數(shù):基類中為其派生類保留一個名字,以便派生類根據(jù)需要進(jìn)行定義。 包含一個純虛函數(shù)的類是抽象類。 純虛函數(shù)后面有 = 0; 抽象類不可以實例化。但可以定義指針。 如果派生類如果不是先基類的純虛函數(shù),則仍然是抽象類。 抽象類可以包含虛函數(shù)。
47、抽象類和接口的區(qū)別
在C++里面抽象類就是接口
抽象類:定義了純虛函數(shù)的類是抽象類,不能實例化。
抽象類包括抽象方法(純虛方法),也可以包含普通方法。 抽象類可以派生自一個抽象類,可以覆蓋基類的抽象方法也可以不覆蓋。
雖不能定義抽象類的實例,但是可以定義抽象類的指針。
48、將引用作為函數(shù)參數(shù)有哪些特點
(1)與指針調(diào)用效果一樣。
(2)引用傳參,內(nèi)存中并沒有產(chǎn)生副本。
(3)用指針傳遞,也要給形參分配存儲單元;并且需要使用"*變量的"的形式,可讀性差;另外,調(diào)用的地方還得用地址作為實參。
49、引用作為函數(shù)返回值類型的格式,好處和規(guī)則?
int &fun(int a) {}
好處:不會生成副本。
規(guī)則:不能返回局部變量的引用;不能返回函數(shù)內(nèi)部new分配的內(nèi)存引用;如果返回成員的話,返回const
50、結(jié)構(gòu)與聯(lián)合的區(qū)別
聯(lián)合是公用存儲單元的,任何一個時刻只有一個被選中的成員。一旦賦值后,其他成員也覆蓋了。
51、重載(overload)和重寫(override)?
重載:多個同名函數(shù),參數(shù)不同(個數(shù)不同,參數(shù)類型不同);是同一層級的函數(shù);靜態(tài)綁定;編譯期綁定。
重寫:子類重新定義父類函數(shù)的方法;是動態(tài)綁定。
52、main函數(shù)之前會執(zhí)行什么代碼?
全局變量的初始化。
53、const 與 #define相比優(yōu)點?
const: 定義常量; 修飾函數(shù)參數(shù); 修飾函數(shù)返回值; 修飾類成員函數(shù)。
好處: const 修飾的有數(shù)據(jù)類型,而宏沒有,所以可以做類型檢查;而宏僅作字符替換,無安全檢查。
const常量可以調(diào)試
宏有副作用,不加括號的話有副作用。
54、為什么基類的析構(gòu)函數(shù)是虛函數(shù)?
動態(tài)綁定,不會造成潛在的內(nèi)存泄漏
55、子類不能繼承父類的函數(shù)有哪些
子類繼承父類大部分的資源,不能繼承的有構(gòu)造函數(shù),析構(gòu)函數(shù),拷貝構(gòu)造函數(shù),operator=函數(shù),友元函數(shù)。
56、虛函數(shù) VS 純虛函數(shù)
虛函數(shù)為了重載和多態(tài),在基類中是有定義的,即便定義為空。在子類中可以重寫。
純虛函數(shù)在基類中沒有定義,必須在子類中實現(xiàn)。
多態(tài)的基礎(chǔ)是繼承,需要虛函數(shù)的支持。
57、開發(fā)中常用的數(shù)據(jù)結(jié)構(gòu):
A:數(shù)組和鏈表:
數(shù)組大小不能動態(tài)定義。鏈表和動態(tài)分配大小的。
數(shù)組不適應(yīng)動態(tài)增/減的情況,因為大小固定,一旦定義就不能改變。
鏈表適合動態(tài)的增加、刪除數(shù)據(jù)。
數(shù)組的隨機(jī)訪問快。
數(shù)組棧中分配; 鏈表在堆中。
B:二叉樹遍歷: 先序、中序、后序。
58、棧溢出的原因:
棧大小有限制:分過多的數(shù)組;
遞歸調(diào)用層太深;
59、頻繁出現(xiàn)的短小的函數(shù),在c/C++中分別如何實現(xiàn)
c中用宏定義; C++ 內(nèi)聯(lián)
60、 C++函數(shù)傳參數(shù)方式
值傳遞、指針、引用
61、 .h頭文件中的ifndef/define/endif作用
防止頭文件重復(fù)包含
62、什么是平衡二叉樹?
左右子樹都是平衡二叉樹 且左右子樹的深度差值的絕對值不大于 1 。
63、用兩個棧實現(xiàn)一個隊列的功能?要求給出算法和思路!
設(shè) 2 個棧為 A,B, 一開始均為空 .
入隊 :
將新元素 push 入棧 A;
出隊 :
(1) 判斷棧 B 是否為空;
(2) 如果不為空,則將棧 A 中所有元素依次 pop 出并 push 到棧 B ;
(3) 將棧 B 的棧頂元素 pop 出;
這樣實現(xiàn)的隊列入隊和出隊的平攤復(fù)雜度都還是 O(1)
64、關(guān)鍵字 static 的作用是什么?
在 C 語言中,關(guān)鍵字 static 有三個明顯的作用:
- 在函數(shù)體,一個被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過程中維持其值不變。
- 在模塊內(nèi)(但在函數(shù)體外),一個被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問。它是一個本地的全局變量。
- 在模塊內(nèi),一個被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。
65、什么是預(yù)編譯 , 何時需要預(yù)編譯 ?
預(yù)編譯又稱為預(yù)處理 , 是做些代碼文本的替換工作。處理 # 開頭的指令 , 比如拷貝 #include 包含的文件代碼, #define 宏定義的替換 , 條件編譯等,就是為編譯做的預(yù)備工作的階段,主要處理 # 開始的預(yù)編譯指令,預(yù)編譯指令指示了在程序正式編譯前就由編譯器進(jìn)行的操作,可以放在程序中的任何位置。
66、Itearator 各指針的區(qū)別
游標(biāo)是指針,但不僅僅是指針。游標(biāo)和指針很像,功能很像指針,但是實際上,游標(biāo)是通過重載一元的 ”*” 和 ”->” 來從容器中間接地返回一個值。將這些值存儲在容器中并不是一個好主意,因為每當(dāng)一個新值添加到容器中或者有一個值從容器中刪除,這些值就會失效。在某種程度上,游標(biāo)可以看作是句柄( handle )。通常情況下游標(biāo)( iterator )的類型可以有所變化,這樣容器也會有幾種不同方式的轉(zhuǎn)變: iterator——對于除了 vector 以外的其他任何容器,你可以通過這種游標(biāo)在一次操作中在容器中朝向前的方向走一步。這意味著對于這種游標(biāo)你只能使用 “++” 操作符。而不能使用 “--” 或 “+=” 操作符。而對于 vector 這一種容器,你可以使用 “+=” 、 “—” 、 “++” 、 “-=” 中的任何一種操作符和 “<” 、 “<=” 、 “>” 、 “>=” 、 “==” 、 “!=” 等比較運算符。
67、數(shù)組和鏈表的優(yōu)缺點
數(shù)組,在內(nèi)存上給出了連續(xù)的空間。鏈表,內(nèi)存地址上可以是不連續(xù)的,每個鏈表的節(jié)點包括原來的內(nèi)存和下一個節(jié)點的信息(單向的一個,雙向鏈表的話,會有兩個)。
數(shù)組優(yōu)于鏈表的:
A. 內(nèi)存空間占用的少。
B. 數(shù)組內(nèi)的數(shù)據(jù)可隨機(jī)訪問,但鏈表不具備隨機(jī)訪問性。
C. 查找速度快
鏈表優(yōu)于數(shù)組的:
A. 插入與刪除的操作方便。
B. 內(nèi)存地址的利用率方面鏈表好。
C. 方便內(nèi)存地址擴(kuò)展。
Linux部分
1、TCP和UDP有什么區(qū)別
TCP---傳輸控制協(xié)議,提供的是面向連接、可靠的字節(jié)流服務(wù)。當(dāng)客戶和服務(wù)器彼此交換數(shù)據(jù)前,必須先在雙方之間建立一個TCP連接,之后才能傳輸數(shù)據(jù)。TCP提供超時重發(fā),丟棄重復(fù)數(shù)據(jù),檢驗數(shù)據(jù),流量控制等功能,保證數(shù)據(jù)能從一端傳到另一端。
UDP---用戶數(shù)據(jù)報協(xié)議,是一個簡單的面向數(shù)據(jù)報的運輸層協(xié)議。
UDP不提供可靠性,它只是把應(yīng)用程序傳給IP層的數(shù)據(jù)報發(fā)送出去,但是并不能保證它們能到達(dá)目的地。由于UDP在傳輸數(shù)據(jù)報前不用在客戶和服務(wù)器之間建立一個連接,且沒有超時重發(fā)等機(jī)制,故而傳輸速度很快
2、編寫socket套接字的步驟
服務(wù)器:建立套接字、綁定、監(jiān)聽、接收連接、讀寫數(shù)據(jù)、關(guān)閉連接
客戶端:建立套接字、連接、讀寫數(shù)據(jù)、關(guān)閉連接
3、同步IO和異步IO的區(qū)別?
A. 同步
所謂同步,就是在發(fā)出一個功能調(diào)用時,在沒有得到結(jié)果之前,該調(diào)用就不返回。
按照這個定義,其實絕大多數(shù)函數(shù)都是同步調(diào)用(例如sin isdigit等)。
但是一般而言,我們在說同步、異步的時候,特指那些需要其他部件協(xié)作或者需要一定時間完成的任務(wù)。
最常見的例子就是 SendMessage。
該函數(shù)發(fā)送一個消息給某個窗口,在對方處理完消息之前,這個函數(shù)不返回。
當(dāng)對方處理完畢以后,該函數(shù)才把消息處理函數(shù)所返回的值返回給調(diào)用者。
B. 異步
異步的概念和同步相對。
當(dāng)一個異步過程調(diào)用發(fā)出后,調(diào)用者不會立刻得到結(jié)果。
實際處理這個調(diào)用的部件是在調(diào)用發(fā)出后,通過狀態(tài)、通知來通知調(diào)用者,或通過回調(diào)函數(shù)處理這個調(diào)用。
4、進(jìn)程間通信的方式有?
進(jìn)程間通信的方式有 :共享內(nèi)存, 管道(有名管道/無名管道),Socket ,消息隊列 ,信號,信號量,內(nèi)存映射等。
5、死鎖的四個必要條件?
互斥,請求保持,不可剝奪,環(huán)路。
6、進(jìn)程和線程的差別。
線程是指進(jìn)程內(nèi)的一個執(zhí)行單元,也是進(jìn)程內(nèi)的可調(diào)度實體.與進(jìn)程的區(qū)別:
(1)調(diào)度:線程作為調(diào)度和分配的基本單位,進(jìn)程作為擁有資源的基本單位
(2)并發(fā)性:不僅進(jìn)程之間可以并發(fā)執(zhí)行,同一個進(jìn)程的多個線程之間也可并發(fā)執(zhí)行
(3)擁有資源:進(jìn)程是擁有資源的一個獨立單位,線程不擁有系統(tǒng)資源,但可以訪問隸屬于進(jìn)程的資源.
(4)系統(tǒng)開銷:在創(chuàng)建或撤消進(jìn)程時,由于系統(tǒng)都要為之分配和回收資源,導(dǎo)致系統(tǒng)的開銷明顯大于創(chuàng)建或撤消線程時的開銷。
7、多線程如何同步
windows線程同步有四種方式:臨界區(qū)、內(nèi)核對象、互斥量、信號量。
Linux線程同步有最常用的是:互斥鎖、條件變量和信號量。