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

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

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

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

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

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

5、就要用int *來申請; int * a= new int * 2;/申請兩個int * 型的空間 a0 = new int4;/為a的第一個元素申請了個int 型空間,a0 指向了此空間的首地址處 a1 = new int3;/為a的第二個元素又申請了個int 型空間,a1指向了此空間首地址處/*/指針數組初始化賦值:一維指針開辟空間: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);結構體指針數組,例如typedef struct char x; int y; Quan,*QQuan;定義一個結構體指針數組如:QQuan aMAX for(i=0;iMAX;i+) ai=(QQuan)malloc(sizeof(Quan); memset(ai,0,sizeof(Quan);指針數組賦值 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,復雜指針解析:(1)int (*func)(int *p);(*func)()是一個函數,func是一個指向這類函數的指針,就是一個函數指針,這類函數具有int*類型的形參,返回值類型是 int。(2)int (*func)(int *p, int (*f)(int*

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

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

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

11、f)(char *, const char *);指向外部函數的指針:void (*pf)(char *, const char *); void strcpy(char * dest, const char * source); pf=strcpy;5,野指針答:“野指針”是很危險的,if語句對它不起作用。“野指針”的成因主要有兩種:(1)指針變量沒有被初始化。指針變量在創建的同時應當被初始化,要么將指針設置為NULL,要么讓它指向合法的內存。char *p = NULL; char *str = (char *) malloc(100);(2)指針p被free或者delete之后,沒有置為

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

13、容不可改,也就是說*p是常量字符串,修飾指針所指向的變量const char * const p 和 char const * const p; / 內容和指針都不能改1)const修飾函數參數是它最廣泛的一種用途,它表示函數體中不能修改參數的值,傳遞過來的參數在函數內不可以改變,參數指針所指內容為常量不可變,參數指針本身為常量不可變在引用或者指針參數的時候使用const限制是有意義的,而對于值傳遞的參數使用const則沒有意義2)const修飾類對象表示該對象為常量對象,其中的任何成員都不能被修改。3)const修飾的對象,該對象的任何非const成員函數都不能被調用,因為任何非const成

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

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

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

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

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

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

20、 / 取址運算符 const 12,談談類和結構體的區別答:結構體在默認情況下的成員都是public的,而類在默認情況下的成員是private的。結構體和類都必須使用new創建,struct保證成員按照聲明順序在內存在存儲,而類不保證。13,C+四種強制類型轉換答:(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、用于基本類型之間和具有繼承關系的類型之間的轉換。用于指針類型的轉換沒有太大的意義static_cast是無條件和靜態類型轉換,可用于基類和子類的轉換,基本類型轉換,把空指針轉換為目標類型的空指針,把任何類型的表達式轉換成void類型,static_cast不能進行無關類型(如非基類和子類)指針之間的轉換。int a; double d = static_cast(a); /基本類型轉換int &pn = &a; void *p = static_cast(pn); /任意類型轉換為void(3)dynamic_cast你可以用它把一個指向基類的指針或引用對象轉換成繼承類的對象動態類型轉換,運行

22、時類型安全檢查(轉換失敗返回NULL)基類必須有虛函數,保持多態特性才能用dynamic_cast只能在繼承類對象的指針之間或引用之間進行類型轉換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、/子類-父類,動態類型轉換,正確(4)reinterpreter_cast轉換的類型必須是一個指針、引用、算術類型、函數指針或者成員指針。主要是將一個類型的指針,轉換為另一個類型的指針不同類型的指針類型轉換用reinterpreter_cast最普通的用途就是在函數指針類型之間進行轉換int DoSomething()return 0;typedef void(*FuncPtr)();FuncPtr funcPtrArray10;funcPtrArray0 = reinterpreter_cast(&DoSomething);14,C+函數中值的傳遞方式有哪幾種?答:函數的三種傳遞方式為:值傳

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

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

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

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

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

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

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

31、塊內的static全局變量可以被模塊內所有函數訪問,但不能被模塊外其它函數訪問;(3)在模塊內的static函數只可被這一模塊內的其它函數調用,這個函數的使用范圍被限制在聲明它的模塊內;(4)在類中的static成員變量屬于整個類所擁有,對類的所有對象只有一份拷貝;(5)在類中的static成員函數屬于整個類所擁有,這個函數不接收this指針,因而只能訪問類的static成員變量。24,頭文件的作用是什么? 答:一,通過頭文件來調用庫功能。在很多場合,源代碼不便(或不準)向用戶公布,只要向用戶提供頭文件和二進制的庫即可。用戶只需要按照頭文件中的接口聲明來調用庫功能,而不必關心接口怎么實現的。編

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

33、函數?答:普通函數(非成員函數),構造函數,內聯成員函數、靜態成員函數、友元函數。(1)虛函數用于基類和派生類,普通函數所以不能(2)構造函數不能是因為虛函數采用的是虛調用的方法,允許在只知道部分信息的情況的工作機制,特別允許調用只知道接口而不知道對象的準確類型的方法,但是調用構造函數即使要創建一個對象,那勢必要知道對象的準確類型。(3)內聯成員函數的實質是在調用的地方直接將代碼擴展開(4)繼承時,靜態成員函數是不能被繼承的,它只屬于一個類,因為也不存在動態聯編等(5)友元函數不是類的成員函數,因此也不能被繼承27, 數組int c33; 為什么c,*c的值相等,(c+1),(*c+1)的值不

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

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

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

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

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

39、AX未知 , void類型那么sizeof(max),sizeof(char_v),sizeof(void)都是錯誤的當sizeof的參數為數組或者指針時int a50; /sizeof(a)=4*50=200; 求數組所占的空間大小 int *a=new int50;/ sizeof(a)=4; a為一個指針,sizeof(a)是求指針 當sizeof的參數為結構或類時候結構或者類中的靜態成員不對結構或者類的大小產生影響,因為靜態變量的存儲位置 。與結構或者類的實例地址無關。沒有成員變量的結構或類的大小為1,因為必須保證結構或類的每一 實例在內存中都有唯一的地址(2)class MyStru

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

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

42、所占用的字節數sizeof(double)=8)的倍數,所以沒有空缺的字節需要填充。34,在main函數執行之前,還會執行什么代碼和工作答:運行全局構造器,全局對象的構造函數會在main函數之前執行設置棧指針,初始化static靜態和global全局變量,即數據段的內容將未初始化部分的賦初值:數值型short,int,long等為0,bool為FALSE,指針為NULL等將main函數的參數,argc,argv等傳遞給main函數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類定義如下,嘗試寫出類的成員函數實現classpublic:String(const char*str = NULL); /通用構造函數String(const String& another); /拷貝構造函數String(); /析構函數St

44、ring& operator = = (const String& rhs); /賦值函數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); /刪除原來的數據,新開一塊內存 strcpy(m_data, rhs.m_data); return *this;String() delete m_data;38,論述C+類繼承的優缺點答:一,優點:類繼承是在編譯時刻靜態定義的,可以直接使用,類繼承可以較方便的改變從父類繼承

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

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

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

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

50、LL。DLL載入后,模塊可以通過調用GetProcAddress獲取DLL函數的出口地址,然后就可以通過返回的函數指針調用DLL函數了。如此即可避免導入庫文件了。44,C和C+有什么不同?答:從機制上:c是面向過程的。c+是面向對象的,提供了類。c+編寫面向對象的程序比c容易。從適用的方向:c適合要求代碼體積小的,效率高的場合,如嵌入式;c+適合更上層的,復雜的; llinux核心大部分是c寫的,因為它是系統軟件,效率要求極高。C語言是結構化編程語言,C+是面向對象編程語言C+側重于對象而不是過程,側重于類的設計而不是邏輯的設計。45,C+編譯器自動為類產生的四個確缺省函數是什么?答:默認構造

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

溫馨提示

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

評論

0/150

提交評論