C+經(jīng)典面試題大全2-完整版(總19頁_第1頁
C+經(jīng)典面試題大全2-完整版(總19頁_第2頁
C+經(jīng)典面試題大全2-完整版(總19頁_第3頁
C+經(jīng)典面試題大全2-完整版(總19頁_第4頁
C+經(jīng)典面試題大全2-完整版(總19頁_第5頁
已閱讀5頁,還剩15頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、 經(jīng)典C+面試題:成為C+程序員之路1,關(guān)于動態(tài)申請內(nèi)存答:內(nèi)存分配方式三種:(1)從靜態(tài)存儲區(qū)域分配:內(nèi)存在程序編譯的時候就已經(jīng)分配好,這塊內(nèi)存在程序的整個運(yùn)行期間都存在。全局變量,static變量。(2)在棧上創(chuàng)建:在執(zhí)行函數(shù)時,函數(shù)內(nèi)局部變量的存儲單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時這些存儲單元自動被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限。(3)用malloc或new申請內(nèi)存之后,應(yīng)該立即檢查指針值是否為NULL.防止使用指針值為NULL的內(nèi)存,不要忘記為數(shù)組和動態(tài)內(nèi)存賦初值。防止將未被初始化的內(nèi)存作為右值使用。避免數(shù)組或指針的下標(biāo)越界,特別要當(dāng)心發(fā)

2、生“多1”或者“少1”操作。動態(tài)內(nèi)存的申請與釋放必須配對,防止內(nèi)存泄漏。用free或delete釋放了內(nèi)存之后,立即將指針設(shè)置為NULL,防止產(chǎn)生“野指針”。從堆上分配,亦稱動態(tài)內(nèi)存分配。程序在運(yùn)行的時候用malloc或new申請任意多少的內(nèi)存,程序員自己負(fù)責(zé)在何時用free或delete釋放內(nèi)存。動態(tài)內(nèi)存的生存期由程序員決定,使用非常靈活。(int *pArray; int MyArray6; pArray = &MyArray0;)如果在申請動態(tài)內(nèi)存時找不到足夠大的內(nèi)存塊,malloc和new將返回NULL指針,判斷指針是否為NULL,如果是則馬上用return語句終止本函數(shù),或者馬上用e

3、xit(1)終止整個程序的運(yùn)行,為new和malloc設(shè)置異常處理函數(shù)。2,C+指針攻破答案:指針是一個變量,專門存放內(nèi)存地址,特點(diǎn)是能訪問所指向的內(nèi)存指針本身占據(jù)了4個字節(jié)的長度int *ptr; /指針的類型是 int *int (*ptr)3; /指針的類型是 int(*)3 int *(*ptr)4; /指針的類型是 int *(*)4 ptr+:指針ptr的值加上了sizeof(int)ptr+=5:將指針ptr的值加上5*sizeof(int)/*/指針的賦值:把一個變量的地址賦予指向相同數(shù)據(jù)類型的指針變量( int a; int *ip; ip=&a; ) 把一個指針變量的值賦予

4、指向相同類型變量的另一個指針變量(int a; int *pa=&a; int *pb; pb=pa; )把數(shù)組的首地址賦予指向數(shù)組的指針變量(int a5,*pa; pa=a; 也可寫為:pa=&a0;)如果給指針加1或減1 ,實(shí)際上是加上或減去指針?biāo)赶虻臄?shù)據(jù)類型大小。當(dāng)給指針加上一個整數(shù)值或減去一個整數(shù)值時,表達(dá)式返回一個新地址。相同類型的兩個指針可以相減,減后返回的整數(shù)代表兩個地址間該類型的實(shí)例個數(shù)。int * cc=new (int*)10; 聲明一個個元素的數(shù)組,數(shù)組每個元素都是一個int *指針,每個元素還可以單獨(dú)申請空間,因?yàn)閏c的類型是int*型的指針,所以你要在堆里申請的話

5、就要用int *來申請; int * a= new int * 2;/申請兩個int * 型的空間 a0 = new int4;/為a的第一個元素申請了個int 型空間,a0 指向了此空間的首地址處 a1 = new int3;/為a的第二個元素又申請了個int 型空間,a1指向了此空間首地址處/*/指針數(shù)組初始化賦值:一維指針開辟空間:char *str;int *arr; scanf(%d,&N);str=(char*)malloc(sizeof(char)*N);arr=(int*)malloc(sizeof(int)*N);二維指針開辟空間:int *arr, i; scanf(%d%

6、d,&row,&col);arr=(int*)malloc(sizeof(int)*row);for(i=0;irow;i+) arri=(int*)malloc(sizeof(int)*col);結(jié)構(gòu)體指針數(shù)組,例如typedef struct char x; int y; Quan,*QQuan;定義一個結(jié)構(gòu)體指針數(shù)組如:QQuan aMAX for(i=0;iMAX;i+) ai=(QQuan)malloc(sizeof(Quan); memset(ai,0,sizeof(Quan);指針數(shù)組賦值 float a=100,200,300,400,500;float *p5=&a0,&a1

7、,&a2,&a3,&a4;char *units1000;char get_unit250;for(int i=0;iget_unit_num;i+) unitsi=(char*) malloc(60*sizeof(char*); scanf(%s, get_unit); strcpy(unitsi,get_unit);/*/3,復(fù)雜指針解析:(1)int (*func)(int *p);(*func)()是一個函數(shù),func是一個指向這類函數(shù)的指針,就是一個函數(shù)指針,這類函數(shù)具有int*類型的形參,返回值類型是 int。(2)int (*func)(int *p, int (*f)(int*

8、);func是一個指向函數(shù)的指針,這類函數(shù)具有int *和int (*)(int*)這樣的形參。形參int (*f)(int*),f也是一個函數(shù)指針(3)int (*func5)(int *p);func數(shù)組的元素是函數(shù)類型的指針,它所指向的函數(shù)具有int*類型的形參,返回值類型為int。(4)int (*(*func)5)(int *p);func是一個指向數(shù)組的指針,這個數(shù)組的元素是函數(shù)指針,這些指針指向具有int*形參,返回值為int類型的函數(shù)。(5)int (*(*func)(int *p)5;func是一個函數(shù)指針,這類函數(shù)具有int*類型的形參,返回值是指向數(shù)組的指針,所指向的數(shù)組

9、的元素是具有5個int元素的數(shù)組。注意:需要聲明一個復(fù)雜指針時,如果把整個聲明寫成上面所示的形式,對程序可讀性是一大損害。應(yīng)該用typedef來對聲明逐層,分解,增強(qiáng)可讀性,例如對于聲明:int (*(*func)(int *p)5;這樣分解:typedef int (*PARA)5; typedef PARA (*func)(int *);例如:int (*(*func)56)78;func是一個指向數(shù)組的指針,這類數(shù)組的元素是一個具有5X6個int元素的二維數(shù)組,而這個二維數(shù)組的元素又是一個二維數(shù)組。typedef int (*PARA)78;typedef PARA (*func)56;

10、例如:int (*(*(*func)(int *)5)(int *);func是一個函數(shù)指針,這類函數(shù)的返回值是一個指向數(shù)組的指針,所指向數(shù)組的元素也是函數(shù)指針,指向的函數(shù)具有int*形參,返回值為int。typedef int (*PARA1)(int*);typedef PARA1 (*PARA2)5;typedef PARA2 (*func)(int*);4,函數(shù)指針詳解答:函數(shù)指針是指向一個函數(shù)入口的指針一個函數(shù)指針只能指向一種類型的函數(shù),即具有相同的返回值和相同的參數(shù)的函數(shù)。函數(shù)指針數(shù)組定義:void(*fun3)(void*); 相應(yīng)指向類A的成員函數(shù)的指針:void (A:*pm

11、f)(char *, const char *);指向外部函數(shù)的指針:void (*pf)(char *, const char *); void strcpy(char * dest, const char * source); pf=strcpy;5,野指針答:“野指針”是很危險的,if語句對它不起作用?!耙爸羔槨钡某梢蛑饕袃煞N:(1)指針變量沒有被初始化。指針變量在創(chuàng)建的同時應(yīng)當(dāng)被初始化,要么將指針設(shè)置為NULL,要么讓它指向合法的內(nèi)存。char *p = NULL; char *str = (char *) malloc(100);(2)指針p被free或者delete之后,沒有置為

12、NULL(3)指針操作超越了變量的作用范圍。所指向的內(nèi)存值對象生命期已經(jīng)被銷毀6,引用和指針有什么區(qū)別?答:1)引用必須初始化,指針則不必;2)引用初始化以后不能改變,指針可以改變其指向的對象;3)不存在指向空值的引用,但存在指向控制的指針;4)引用是某個對象的別名,主要用來描述函數(shù)和參數(shù)和返回值。指針與一般的變量是一樣的,會在內(nèi)存中開辟一塊內(nèi)存。5)如果函數(shù)的參數(shù)或返回值是類的對象的話,采用引用可以提高程序的效率。7,C+中的Const用法答:char * const p; / 指針不可改,也就說指針只能指向一個地址,不能更改為其他地址,修飾指針本身char const * p; / 所指內(nèi)

13、容不可改,也就是說*p是常量字符串,修飾指針?biāo)赶虻淖兞縞onst char * const p 和 char const * const p; / 內(nèi)容和指針都不能改1)const修飾函數(shù)參數(shù)是它最廣泛的一種用途,它表示函數(shù)體中不能修改參數(shù)的值,傳遞過來的參數(shù)在函數(shù)內(nèi)不可以改變,參數(shù)指針?biāo)竷?nèi)容為常量不可變,參數(shù)指針本身為常量不可變在引用或者指針參數(shù)的時候使用const限制是有意義的,而對于值傳遞的參數(shù)使用const則沒有意義2)const修飾類對象表示該對象為常量對象,其中的任何成員都不能被修改。3)const修飾的對象,該對象的任何非const成員函數(shù)都不能被調(diào)用,因?yàn)槿魏畏莄onst成

14、員函數(shù)會有修改成員變量的企圖。4)const修飾類的成員變量,表示成員常量,不能被修改,同時它只能在初始化列表中賦值。static const 的成員需在聲明的地方直接初始。5)const修飾類的成員函數(shù),則該成員函數(shù)不能修改類中任何非const成員。一般寫在函數(shù)的最后來修飾。在函數(shù)實(shí)現(xiàn)部分也要帶const關(guān)鍵字.6)對于const類對象/指針/引用,只能調(diào)用類的const成員函數(shù),因此,const修飾成員函數(shù)的最重要作用就是限制對于const對象的使用7)使用const的一些建議:在參數(shù)中使用const應(yīng)該使用引用或指針,而不是一般的對象實(shí)例const在成員函數(shù)中的三種用法(參數(shù)、返回值、函

15、數(shù))要很好的使用;不要輕易的將函數(shù)的返回值類型定為const;除了重載操作符外一般不要將返回值類型定為對某個對象的const引用;8,const常量與define宏定義的區(qū)別答:(1) 編譯器處理方式不同。define宏是在預(yù)處理階段展開,生命周期止于編譯期。define只是一個常數(shù)、一個命令中的參數(shù),沒有實(shí)際的存在。#define常量存在于程序的代碼段。const常量是編譯運(yùn)行階段使用,const常量存在于程序的數(shù)據(jù)段.(2)類型和安全檢查不同。define宏沒有類型,不做任何類型檢查,僅僅是展開。const常量有具體的類型,在編譯階段會執(zhí)行類型檢查。(3) 存儲方式不同。define宏僅僅

16、是展開,有多少地方使用,就展開多少次,不會分配內(nèi)存。const常量會在內(nèi)存中分配(可以是堆中也可以是棧中)9,解釋堆和棧的區(qū)別答:1)棧區(qū)(stack) 由編譯器自動分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。2)由系統(tǒng)自動分配,速度較快,但程序員無法控制。聲明在函數(shù)中一個局部變量 int b; 系統(tǒng)自動在棧中為b開辟空間 。3)只要棧的剩余空間大于所申請空間,系統(tǒng)將為程序提供內(nèi)存,如果申請空間超過棧剩余空間時,將提示overflow。4)在Windows下,棧是高地址向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域,棧的大小是2M。5)棧由系統(tǒng)自動分配函數(shù)調(diào)用

17、時,第一個進(jìn)棧的是主函數(shù)中后的下一條指令的地址,然后是函數(shù)的各個參數(shù)。6)在大多數(shù)的C編譯器中,參數(shù)是由右往左入棧的,然后是函數(shù)中的局部變量。注意靜態(tài)變量是不入棧的。堆區(qū)(heap) 1)一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時可能由OS回收 。2)注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,分配方式倒是類似于鏈表,需要程序員自己申請,并指明大小,在c中malloc函數(shù)在C+中用new運(yùn)算符。首先應(yīng)該知道操作系統(tǒng)有一個記錄空閑內(nèi)存地址的鏈表,當(dāng)系統(tǒng)收到程序的申請時在鏈表中尋找,另外,由于找到的堆結(jié)點(diǎn)的大小不一定正好等于申請的大小,系統(tǒng)會自動的將多余的那部分重新放入空閑鏈表中。3)堆是低地址向高地

18、址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域。鏈表的遍歷方向是由低地址向高地址。4)堆的大小受限于計算機(jī)系統(tǒng)中有效的虛擬內(nèi)存。5)堆是由new分配的內(nèi)存,一般速度比較慢,而且容易產(chǎn)生內(nèi)存碎片,不過用起來最方便,一般是在堆的頭部用一個字節(jié)存放堆的大小。10,論述含參數(shù)的宏和函數(shù)的優(yōu)缺點(diǎn)(1)函數(shù)調(diào)用時,先求出實(shí)參表達(dá)式的值,然后代入形參。而使用帶參的宏只是進(jìn)行簡單的字符替換(2)函數(shù)調(diào)用是在程序運(yùn)行時處理的,分配臨時的內(nèi)存單元;而宏展開是在編譯時進(jìn)行的,在展開時不進(jìn)行內(nèi)存分配,不進(jìn)行值得傳遞處理,沒有“返回值”概念(3)對函數(shù)中的形參和實(shí)參都要定義類型,類型要求一致,如不一致則進(jìn)行類型轉(zhuǎn)換。而宏不存在類

19、型問題(4)調(diào)用函數(shù)只可得到一個返回值,而用宏則可以設(shè)法得到幾個結(jié)果(5)實(shí)用宏次數(shù)多時,宏展開后源程序變長,沒展開一次源程序增長,函數(shù)調(diào)用則不會(6)宏替換不占用運(yùn)行時間,只占編譯時間,而函數(shù)調(diào)用占用運(yùn)行時間11,C+的空類,默認(rèn)產(chǎn)生哪些類成員函數(shù)?答:class Empty public:Empty(); /缺省構(gòu)造函數(shù)Empty(const Empty& ); /拷貝構(gòu)造函數(shù)Empty(); /虛構(gòu)函數(shù)Empty& operator(const Empty& ) /賦值運(yùn)算符Empty& operator&(); /取址運(yùn)算符const Empty* operator&() const;

20、 / 取址運(yùn)算符 const 12,談?wù)勵惡徒Y(jié)構(gòu)體的區(qū)別答:結(jié)構(gòu)體在默認(rèn)情況下的成員都是public的,而類在默認(rèn)情況下的成員是private的。結(jié)構(gòu)體和類都必須使用new創(chuàng)建,struct保證成員按照聲明順序在內(nèi)存在存儲,而類不保證。13,C+四種強(qiáng)制類型轉(zhuǎn)換答:(1)const_cast字面上理解就是去const屬性,去掉類型的const或volatile屬性。struct SA int k; const SA ra; ra.k = 10; /直接修改const類型,編譯錯誤 SA& rb = const_cast(ra); rb.k = 10; /可以修改(2)static_cast主要

21、用于基本類型之間和具有繼承關(guān)系的類型之間的轉(zhuǎn)換。用于指針類型的轉(zhuǎn)換沒有太大的意義static_cast是無條件和靜態(tài)類型轉(zhuǎn)換,可用于基類和子類的轉(zhuǎn)換,基本類型轉(zhuǎn)換,把空指針轉(zhuǎn)換為目標(biāo)類型的空指針,把任何類型的表達(dá)式轉(zhuǎn)換成void類型,static_cast不能進(jìn)行無關(guān)類型(如非基類和子類)指針之間的轉(zhuǎn)換。int a; double d = static_cast(a); /基本類型轉(zhuǎn)換int &pn = &a; void *p = static_cast(pn); /任意類型轉(zhuǎn)換為void(3)dynamic_cast你可以用它把一個指向基類的指針或引用對象轉(zhuǎn)換成繼承類的對象動態(tài)類型轉(zhuǎn)換,運(yùn)行

22、時類型安全檢查(轉(zhuǎn)換失敗返回NULL)基類必須有虛函數(shù),保持多態(tài)特性才能用dynamic_cast只能在繼承類對象的指針之間或引用之間進(jìn)行類型轉(zhuǎn)換class BaseClasspublic: int m_iNum; virtual void foo();class DerivedClass:BaseClasspublic: char* szName100; void bar();BaseClass* pb = new DerivedClass();DerivedClass *p2 = dynamic_cast(pb);BaseClass* pParent = dynamic_cast(p2);

23、/子類-父類,動態(tài)類型轉(zhuǎn)換,正確(4)reinterpreter_cast轉(zhuǎn)換的類型必須是一個指針、引用、算術(shù)類型、函數(shù)指針或者成員指針。主要是將一個類型的指針,轉(zhuǎn)換為另一個類型的指針不同類型的指針類型轉(zhuǎn)換用reinterpreter_cast最普通的用途就是在函數(shù)指針類型之間進(jìn)行轉(zhuǎn)換int DoSomething()return 0;typedef void(*FuncPtr)();FuncPtr funcPtrArray10;funcPtrArray0 = reinterpreter_cast(&DoSomething);14,C+函數(shù)中值的傳遞方式有哪幾種?答:函數(shù)的三種傳遞方式為:值傳

24、遞、指針傳遞和引用傳遞。15,將“引用”作為函數(shù)參數(shù)有哪些特點(diǎn)答:(1)傳遞引用給函數(shù)與傳遞指針的效果是一樣的,這時,被調(diào)函數(shù)的形參就成為原來主調(diào)函數(shù)的實(shí)參變量或者對象的一個別名來使用,所以在被調(diào)函數(shù)中形參的操作就是對相應(yīng)的目標(biāo)對象的操作(2)使用引用傳遞函數(shù)的參數(shù),在內(nèi)存中并沒有產(chǎn)生實(shí)參的副本,它是直接對實(shí)參操作,當(dāng)參數(shù)數(shù)據(jù)較大時,引用傳遞參數(shù)的效率和所占空間都好(3)如果使用指針要分配內(nèi)存單元,需要重復(fù)使用“*指針變量名”形式進(jìn)行計算,容易出錯且閱讀性較差。16,簡單敘述面向?qū)ο蟮娜齻€基本特征答:封裝性把客觀事物封裝成抽象的類,對自身的數(shù)據(jù)和方法進(jìn)行(public,private, pro

25、tected)繼承性繼承概念的實(shí)現(xiàn)方式有三類:實(shí)現(xiàn)繼承、接口繼承和可視繼承。實(shí)現(xiàn)繼承是指使用基類的屬性和方法而無需額外編碼的能力;接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實(shí)現(xiàn)的能力;可視繼承是指子窗體(類)使用基窗體(類)的外觀和實(shí)現(xiàn)代碼的能力。抽象類僅定義將由子類創(chuàng)建的一般屬性和方法,創(chuàng)建抽象類時,請使用關(guān)鍵字 Interface 而不是 Class多態(tài)性多態(tài)性(polymorphisn)是允許你將父對象設(shè)置成為和一個或更多的他的子對象相等的技術(shù),賦值之后,父對象就可以根據(jù)當(dāng)前賦值給它的子對象的特性以不同的方式運(yùn)作。允許將子類類型的指針賦值給父類類型的指針。實(shí)現(xiàn)多態(tài),有二種方式,

26、覆蓋(子類重新定義父類的虛函數(shù)),重載(允許存在多個同名函數(shù),參數(shù)個數(shù),類型不同)。17,類成員函數(shù)的overload, override 和 隱藏的區(qū)別答:(1)成員函數(shù)被重載的特征:相同的類范圍,函數(shù)名字相同,參數(shù)不同,virtual 關(guān)鍵字可有可無。(2)覆蓋指派生類的函數(shù)覆蓋基類函數(shù),特征是分別位于基類和派生類,函數(shù)名字相同,參數(shù)相同,基類函數(shù)必須有virtual關(guān)鍵字(3)隱藏是指派生類的函數(shù)屏蔽了與其同名的基類函數(shù)。1,派生類的函數(shù)與基類的函數(shù)同名,但是參數(shù)不同,不論有無virtual關(guān)鍵字,基類的函數(shù)將被隱藏 2,派生類的函數(shù)與基類的函數(shù)同名,并且參數(shù)也相同,但是基類函數(shù)沒有vi

27、rtual 關(guān)鍵字。此時,基類的函數(shù)被隱藏3種情況怎么執(zhí)行:重載:看參數(shù);隱藏:用什么就調(diào)用什么;覆蓋:調(diào)用派生類 。18,什么是預(yù)編譯,何時需要預(yù)編譯答:就是指程序執(zhí)行前的一些預(yù)處理工作,主要指#表示的.需要預(yù)編譯的情況:總是使用不經(jīng)常改動的大型代碼體。所有模塊都使用一組標(biāo)準(zhǔn)的包含文件和相同的編譯選項(xiàng)。 19,memset ,memcpy 和strcpy 的根本區(qū)別? 答:memset用來對一段內(nèi)存空間全部設(shè)置為某個字符,一般用在對定義的字符串進(jìn)行初始化為;它對較大的結(jié)構(gòu)體或數(shù)組進(jìn)行清零操作的一種最快方法。char temp30; memset(temp,0,sizeof(temp);cha

28、r temp30只是分配了一定的內(nèi)存空間給該字符數(shù)組,但并未初始化該內(nèi)存空間,即數(shù)組。所以,需要使用memset()來進(jìn)行初始化。memcpy用來做內(nèi)存拷貝,你可以拿它拷貝任何數(shù)據(jù)類型的對象,可以指定拷貝的數(shù)據(jù)長度;strcpy就只能拷貝字符串了,它遇到0就結(jié)束拷貝;例:char a100,b50;strcpy(a,b);20,多態(tài)類中的虛函數(shù)表是Compile-Time,還是Run-Time時建立的?答:虛擬函數(shù)表是在編譯期就建立了,各個虛擬函數(shù)這時被組織成了一個虛擬函數(shù)的入口地址的數(shù)組.而對象的隱藏成員-虛擬函數(shù)表指針是在運(yùn)行期也就是構(gòu)造函數(shù)被調(diào)用時進(jìn)行初始化的,這是實(shí)現(xiàn)多態(tài)的關(guān)鍵. 21

29、,Template有什么特點(diǎn)?什么時候用?答: Template可以獨(dú)立于任何特定的類型編寫代碼,是泛型編程的基礎(chǔ).當(dāng)我們編寫的類和函數(shù)能夠多態(tài)的用于跨越編譯時不相關(guān)的類型時,用Template.模板主要用于STL中的容器,算法,迭代器等以及模板元編程.C+的template是實(shí)現(xiàn)在庫設(shè)計和嵌入式設(shè)計中的關(guān)鍵,能實(shí)現(xiàn)抽象和效率的結(jié)合;同時template還能有效地防止代碼膨脹C+中為什么用模板類?1)可用來創(chuàng)建動態(tài)增長和減小的數(shù)據(jù)結(jié)構(gòu)2)它是類型無關(guān)的,因此具有很高的可復(fù)用性3)它在編譯時而不是運(yùn)行時檢查數(shù)據(jù)類型,保證了類型安全4)它是平臺無關(guān)的,可移植性5)可用于基本數(shù)據(jù)類型22,進(jìn)程和線程

30、的差別?答:線程是指進(jìn)程內(nèi)的一個執(zhí)行單元,也是進(jìn)程內(nèi)的可調(diào)度實(shí)體.區(qū)別:(1)調(diào)度:線程作為調(diào)度和分配的基本單位,進(jìn)程作為擁有資源的基本單位(2)并發(fā)性:不僅進(jìn)程之間可以并發(fā)執(zhí)行,同一個進(jìn)程的多個線程之間也可并發(fā)執(zhí)行(3)擁有資源:進(jìn)程是擁有資源的一個獨(dú)立單位,線程不擁有系統(tǒng)資源,但可以訪問隸屬于進(jìn)程的資源. (4)系統(tǒng)開銷:創(chuàng)建撤消進(jìn)程,系統(tǒng)都要為之分配和回收資源,系統(tǒng)的開銷明顯大于創(chuàng)建撤消線程多進(jìn)程與多線程,兩者都可以提高程序的并發(fā)度,提高程序運(yùn)行效率和響應(yīng)時間。23,請說出static關(guān)鍵字盡可能多的作用答:(1)函數(shù)體內(nèi)作用范圍為該函數(shù)體,該變量內(nèi)存只被分配一次,具有記憶能力(2)在模

31、塊內(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成員變量。24,頭文件的作用是什么? 答:一,通過頭文件來調(diào)用庫功能。在很多場合,源代碼不便(或不準(zhǔn))向用戶公布,只要向用戶提供頭文件和二進(jìn)制的庫即可。用戶只需要按照頭文件中的接口聲明來調(diào)用庫功能,而不必關(guān)心接口怎么實(shí)現(xiàn)的。編

32、譯器會從庫中提取相應(yīng)的代碼。 二,頭文件能加強(qiáng)類型安全檢查。如果某個接口被實(shí)現(xiàn)或被使用時,其方式與頭文件中的聲明不一致,編譯器就會指出錯誤,這一簡單的規(guī)則能大大減輕程序員調(diào)試、改錯的負(fù)擔(dān)。 25,在C+程序中調(diào)用C編譯后的函數(shù),為什么要加extern C的聲明?答:因?yàn)镃+支持函數(shù)重載,而C不支持函數(shù)重載,函數(shù)被C+編譯后在庫中的名字與C語言的不同。假設(shè)某個函數(shù)的原型為:void foo(int x, int y);該函數(shù)被C編譯器編譯后在庫中的名字為_foo,而C+編譯器則產(chǎn)生像_foo_int_int之類的名字。 C+提供extern C來解決名字匹配問題26,C+中哪些函數(shù)不能被聲明為虛

33、函數(shù)?答:普通函數(shù)(非成員函數(shù)),構(gòu)造函數(shù),內(nèi)聯(lián)成員函數(shù)、靜態(tài)成員函數(shù)、友元函數(shù)。(1)虛函數(shù)用于基類和派生類,普通函數(shù)所以不能(2)構(gòu)造函數(shù)不能是因?yàn)樘摵瘮?shù)采用的是虛調(diào)用的方法,允許在只知道部分信息的情況的工作機(jī)制,特別允許調(diào)用只知道接口而不知道對象的準(zhǔn)確類型的方法,但是調(diào)用構(gòu)造函數(shù)即使要創(chuàng)建一個對象,那勢必要知道對象的準(zhǔn)確類型。(3)內(nèi)聯(lián)成員函數(shù)的實(shí)質(zhì)是在調(diào)用的地方直接將代碼擴(kuò)展開(4)繼承時,靜態(tài)成員函數(shù)是不能被繼承的,它只屬于一個類,因?yàn)橐膊淮嬖趧討B(tài)聯(lián)編等(5)友元函數(shù)不是類的成員函數(shù),因此也不能被繼承27, 數(shù)組int c33; 為什么c,*c的值相等,(c+1),(*c+1)的值不

34、等, c,*c,*c,代表什么意思?答:c是第一個元素的地址,*c是第一行元素的首地址,其實(shí)第一行元素的地址就是第一個元素的地址,*c是提領(lǐng)第一個元素。 為什么c,*c的值相等? c: 數(shù)組名;是一個二維指針,它的值就是數(shù)組的首地址,也即第一行元素的首地址(等于 *c),也等于第一行第一個元素的地址( & c00);可以說成是二維數(shù)組的行指針。*c: 第一行元素的首地址;是一個一維指針,可以說成是二維數(shù)組的列指針。 *c:二維數(shù)組中的第一個元素的值;即:c00 所以:c 和 *c的值是相等的,但他們兩者不能相互賦值,(類型不同)(c + 1) :c是行指針,(c + 1)是在c的基礎(chǔ)上加上二維

35、數(shù)組一行的地址長度,即從&c00變到了&c10; (*c + 1):*c是列指針,(*c + 1)是在*c的基礎(chǔ)上加上二數(shù)組一個元素的所占的長度,&c00變到了&c01,從而(c + 1)和(*c + 1)的值就不相等了。28,定義 int *pa43,則變量pa占有的內(nèi)存空間是多少?答:int *p,在32位機(jī)器上 sizeof(p) = 4;總共占有4*3*sizeof(p) = 48.29,拷貝構(gòu)造函數(shù)相關(guān)問題,深拷貝,淺拷貝,臨時對象等答:在C+中,三種對象需要拷貝的情況:一個對象以值傳遞的方式傳入函數(shù)體, 一個對象以值傳遞的方式從函數(shù)返回,一個對象需要通過另外一個對象進(jìn)行初始化。執(zhí)行

36、先父類后子類的構(gòu)造,對類中每一個數(shù)據(jù)成員遞歸地執(zhí)行成員拷的動作.深拷貝:如果一個類擁有資源,深拷貝意味著拷貝了資源和指針淺拷貝:如果對象存在資源,而淺拷貝只是拷貝了指針,沒有拷貝資源,這樣使得兩個指針指向同一份資源,造成對同一份析構(gòu)兩次,程序崩潰。臨時對象的開銷比局部對象小些。臨時對象:輔助一個表達(dá)式的計算 a + b + c ,或者間接構(gòu)造的實(shí)參,函數(shù)返回非引用的時候,都可能產(chǎn)生臨時對象,臨時對象生命周期,是單個語句,是右值。臨時對象的開銷比局部對象小些。30,指針和引用有什么分別;答:引用必須初始化,即引用到一個有效的對象;而指針在定義的時候不必初始化,可以在定義后面的任何地方重新賦值。引

37、用初始化后不能改變,指針可以改變所指的對象不存在指向NULL的引用,但存在指向NULL的指針引用的創(chuàng)建和銷毀并不會調(diào)用類的拷貝構(gòu)造函數(shù)語言層面,引用的用法和對象一樣;在二進(jìn)制層面,引用一般都是通過指針來實(shí)現(xiàn)的,只不過編譯器幫我們完成了轉(zhuǎn)換.引用既具有指針的效率,又具有變量使用的方便性和直觀性31,寫一個標(biāo)準(zhǔn)宏MIN,這個宏輸入兩個參數(shù)并返回較小的一個答:面試者注意謹(jǐn)慎將宏定義中的“參數(shù)”和整個宏用括號括起來#define MIN(A, B) (A) e )解析:其中(struc*)0表示將常量0轉(zhuǎn)化為struc*類型指針?biāo)赶虻牡刂贰?( (struc*)0)-e )表示取結(jié)構(gòu)體指針(stru

38、c*)0的成員e的地址,因?yàn)樵摻Y(jié)構(gòu)體的首地址為0,所以其實(shí)就是得到了成員e距離結(jié)構(gòu)體首地址的偏移量,(size_t)是一種數(shù)據(jù)類型,為了便于不同系統(tǒng)之間的移植,最好定義為一種無符號型數(shù)據(jù),一般為unsigned int33,解析sizeof 以及 結(jié)構(gòu)體的對齊問題答:(1)sizeof(type),用于數(shù)據(jù)類型;sizeof(var_name)或sizeofvar_name用于變量sizeof操作符不能用于函數(shù)類型,不完全類型或位字段。不完全類型指具有未知存儲大小的數(shù)據(jù)類型,如未知存儲大小的數(shù)組類型、未知內(nèi)容的結(jié)構(gòu)或聯(lián)合類型、void類型等。如intmax(), charchar_vMAX且M

39、AX未知 , void類型那么sizeof(max),sizeof(char_v),sizeof(void)都是錯誤的當(dāng)sizeof的參數(shù)為數(shù)組或者指針時int a50; /sizeof(a)=4*50=200; 求數(shù)組所占的空間大小 int *a=new int50;/ sizeof(a)=4; a為一個指針,sizeof(a)是求指針 當(dāng)sizeof的參數(shù)為結(jié)構(gòu)或類時候結(jié)構(gòu)或者類中的靜態(tài)成員不對結(jié)構(gòu)或者類的大小產(chǎn)生影響,因?yàn)殪o態(tài)變量的存儲位置 。與結(jié)構(gòu)或者類的實(shí)例地址無關(guān)。沒有成員變量的結(jié)構(gòu)或類的大小為1,因?yàn)楸仨毐WC結(jié)構(gòu)或類的每一 實(shí)例在內(nèi)存中都有唯一的地址(2)class MyStru

40、ct double ddal; char dda; int type;在VC中測試上面結(jié)構(gòu)的大小時,你會發(fā)現(xiàn)sizeof(MyStruct)為16。其實(shí),這是VC對變量存儲的一個特殊處理。為了提高CPU的存儲速度,VC對一些變量的起始 地址做了“對齊”處理。在默認(rèn)情況下,VC規(guī)定各成員變量存放的起始地址相對于結(jié)構(gòu)的始地址偏移量必須為該變量的類型占用字節(jié)數(shù)的倍數(shù),如Char偏移量為sizeof(char)即1的倍數(shù)先為第一個成員dda1分配空間,其起始地址跟結(jié)構(gòu)的起始地址相同,偏移量0剛好為sizeof(double)的倍數(shù),該成員變量占用sizeof(double)=8個字節(jié);接下來為第二個成

41、員dda分配空間,這時 下一個可以分配的地址對于結(jié)構(gòu)的起始地址的偏移量為8,是sizeof(char)的倍數(shù),占sizeof(char)=1字節(jié)為第三個成員type分配空間,這時下一個可以分配的地址對于結(jié)構(gòu)的起始地址的偏移量為9,不是sizeof(int)=4的倍數(shù),為了滿足對齊方式對偏移量的約束問題,VC自動填充3個字節(jié) 這時下一個可以分配的地址對于結(jié)構(gòu)的起始地址的偏移量是12,剛好是sizeof(int)=4的倍數(shù),所以把type存放在偏移量為12的地方,占 用sizeof(int)=4個字節(jié)。總的占用的空間大 小為:8+1+3+4=16,剛好為結(jié)構(gòu)的字節(jié)邊界數(shù)(即結(jié)構(gòu)中占用最大空間的類型

42、所占用的字節(jié)數(shù)sizeof(double)=8)的倍數(shù),所以沒有空缺的字節(jié)需要填充。34,在main函數(shù)執(zhí)行之前,還會執(zhí)行什么代碼和工作答:運(yùn)行全局構(gòu)造器,全局對象的構(gòu)造函數(shù)會在main函數(shù)之前執(zhí)行設(shè)置棧指針,初始化static靜態(tài)和global全局變量,即數(shù)據(jù)段的內(nèi)容將未初始化部分的賦初值:數(shù)值型short,int,long等為0,bool為FALSE,指針為NULL等將main函數(shù)的參數(shù),argc,argv等傳遞給main函數(shù)35,如何判斷一段程序是由C 編譯程序還是由C+ 編譯程序編譯的?答:C+ 編譯時定義了 _cplusplus C 編譯時定義了 _STDC_ 36,分別寫出BOOL

43、,int, float, 指針類型的變量 a 與 “零值”的比較語句答: BOOL: if(!a) or if(a) int : if( 0 = a) float : const EXPRESSION EXP = 0.000001; if(a -EXP) pointer: if(a != NULL) or if(a = NULL)37,已知String類定義如下,嘗試寫出類的成員函數(shù)實(shí)現(xiàn)classpublic:String(const char*str = NULL); /通用構(gòu)造函數(shù)String(const String& another); /拷貝構(gòu)造函數(shù)String(); /析構(gòu)函數(shù)St

44、ring& operator = = (const String& rhs); /賦值函數(shù)private:char* m_data; /用于保存字符串; 答:String:String(const char*str) if(str = NULL) m_data = new char1; m_data0 = 0; else m_data = new charstrlen(str)+1; strcpy(m_data, str); String:String(const String& another) m_data = new charstrlen(another.m_data)+1; strcp

45、y(m_data, another.m_data); String:String& operator = = (const String& rhs) if(this = &rhs) return &this; delete m_data; m_data = new char(strlen(rhs.m_data)+1); /刪除原來的數(shù)據(jù),新開一塊內(nèi)存 strcpy(m_data, rhs.m_data); return *this;String() delete m_data;38,論述C+類繼承的優(yōu)缺點(diǎn)答:一,優(yōu)點(diǎn):類繼承是在編譯時刻靜態(tài)定義的,可以直接使用,類繼承可以較方便的改變從父類繼承

46、的實(shí)現(xiàn)二,缺點(diǎn):1,因?yàn)槔^承在編譯時刻就定義了,所以無法在運(yùn)行時刻改變從父類繼承的實(shí)現(xiàn)2,父類通常至少定義了子類的部分行為,父類的任何改變都可能影響到子類的行為3,如果繼承下來的實(shí)現(xiàn)不適合解決新的問題,則父類必須重寫或被其他更適合的類替換這種依賴關(guān)系先限制了靈活性并最終限制了復(fù)用性39,運(yùn)算符重載的三種方式和不允許重載的5個運(yùn)算符答:運(yùn)算符重載意義是為了對用戶自定義數(shù)據(jù)的操作和內(nèi)定義的數(shù)據(jù)類型的操作形式一致(1)普通函數(shù),友元函數(shù),類成員函數(shù)(2).*(成員指針訪問運(yùn)算符) :(域運(yùn)算符) sizeof 長度運(yùn)算符 ?:條件運(yùn)算符 .(成員訪問運(yùn)算符)40,友元關(guān)系有什么特性?答:單向的,非傳

47、遞的, 不能繼承的.41,理解析構(gòu)函數(shù)和虛函數(shù)的用法和作用?答:析構(gòu)函數(shù)也是特殊的類成員函數(shù),它沒有返回類型,沒有參數(shù),不能隨意調(diào)用,也沒有重載。在類對象生命期結(jié)束的時候,由系統(tǒng)自動調(diào)用釋放在構(gòu)造函數(shù)中分配的資源。析構(gòu)函數(shù)一般在對象撤消前做收尾工作,比如回收內(nèi)存等工作。虛函數(shù)的功能是使子類可以用同名的函數(shù)對父類函數(shù)進(jìn)行重載,并且在調(diào)用時自動調(diào)用子類重載函數(shù),在基類中通過使用關(guān)鍵字virtual來聲明一個函數(shù)為虛函數(shù),該函數(shù)的功能可能在將來的派生類中定義或者在基類的基礎(chǔ)上擴(kuò)展,系統(tǒng)只能在運(yùn)行階段才能動態(tài)的決定調(diào)用哪一個函數(shù),動態(tài)的多態(tài)性,如果是純虛函數(shù),則純粹是為了在子類重載時有個統(tǒng)一的命名而已

48、。42,關(guān)鍵字volatile有什么含意?并給出三個不同的例子答:一個定義為volatile的變量是說這變量可能會被意想不到地改變,編譯器就不會去假設(shè)這個變量的值了。精確地說就是,優(yōu)化器在用到這個變量時必須每次都小心地重新讀取這個變量的值而不是使用保存在寄存器里的備份。下面是volatile變量的幾個例子:1) 并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)2) 一個中斷服務(wù)子程序中會訪問到的非自動變量(Non-automatic variables)3) 多線程應(yīng)用中被幾個任務(wù)共享的變量深究:一個參數(shù)既可以是const還可以是volatile,一個例子是只讀的狀態(tài)寄存器,它是volatile因?yàn)樗?/p>

49、能被意想不到地改變,是const因?yàn)槌绦虿粦?yīng)該試圖去修改它。一個指針可以是volatile,一個例子是當(dāng)一個中服務(wù)子程序修該一個指向一個buffer的指針時。43,動態(tài)連接庫的兩種方式?答:調(diào)用一個DLL中的函數(shù)有兩種方法:1載入時動態(tài)鏈接(load-time dynamic linking),模塊非常明確調(diào)用某個導(dǎo)出函數(shù),使得他們就像本地函數(shù)一樣。這需要鏈接時鏈接那些函數(shù)所在DLL的導(dǎo)入庫,導(dǎo)入庫向系統(tǒng)提供了載入DLL時所需的信息及DLL函數(shù)定位。 2運(yùn)行時動態(tài)鏈接(run-time dynamic linking),運(yùn)行時可以通過LoadLibrary或LoadLibraryEx函數(shù)載入D

50、LL。DLL載入后,模塊可以通過調(diào)用GetProcAddress獲取DLL函數(shù)的出口地址,然后就可以通過返回的函數(shù)指針調(diào)用DLL函數(shù)了。如此即可避免導(dǎo)入庫文件了。44,C和C+有什么不同?答:從機(jī)制上:c是面向過程的。c+是面向?qū)ο蟮?,提供了類。c+編寫面向?qū)ο蟮某绦虮萩容易。從適用的方向:c適合要求代碼體積小的,效率高的場合,如嵌入式;c+適合更上層的,復(fù)雜的; llinux核心大部分是c寫的,因?yàn)樗窍到y(tǒng)軟件,效率要求極高。C語言是結(jié)構(gòu)化編程語言,C+是面向?qū)ο缶幊陶Z言C+側(cè)重于對象而不是過程,側(cè)重于類的設(shè)計而不是邏輯的設(shè)計。45,C+編譯器自動為類產(chǎn)生的四個確缺省函數(shù)是什么?答:默認(rèn)構(gòu)造

51、函數(shù),拷貝構(gòu)造函數(shù),析構(gòu)函數(shù),賦值函數(shù)46,簡單描述Windows內(nèi)存管理的方法。答:程序運(yùn)行時需要從內(nèi)存中讀出這段程序的代碼,代碼的位置必須在物理內(nèi)存中才能被運(yùn)行,由于現(xiàn)在的操作系統(tǒng)中有非常多的程序運(yùn)行著,內(nèi)存中不能夠完全放下,所以引出了虛擬內(nèi)存的概念。把哪些不常用的程序片斷就放入虛擬內(nèi)存,當(dāng)需要用到它的時候在load入主存(物理內(nèi)存)中。內(nèi)存管理也計算程序片段在主存中的物理位置,以便CPU調(diào)度。內(nèi)存管理有塊式管理,頁式管理,段式和段頁式管理?,F(xiàn)在常用段頁式管理塊式管理:把主存分為一大塊、一大塊的,當(dāng)所需的程序片斷不在主存時就分配一塊主存空間,把程 序片斷l(xiāng)oad入主存,就算所需的程序片度只有幾個字節(jié)也只能把這一塊分配給它。這樣會造成很大的浪費(fèi),平均浪費(fèi)了50的內(nèi)存空間,但時易于管理。頁式管理:把主存分為一頁一頁的,每一頁的空間要比一塊一塊的空間小很多,顯然這種方法的空間利用率要比塊式管理高很多段式管理:把主存分為一段一段的,每一段的空間又要比一頁一頁的空間小很多,這種方法在空間利用率上又比頁式管理高很多,但是也有另外一個缺點(diǎn)。一個程序片斷可能會被分為幾十段,這樣很多時間就會被浪費(fèi)在計算每一段的物理地址上,計算機(jī)最耗時間的大家都知道是I/O吧段頁式管理:結(jié)合了段式管理和頁式管理的優(yōu)點(diǎn)。把主存

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論