一规辱、編程語(yǔ)言
Linux后臺(tái)開(kāi)發(fā)技術(shù)視頻篇
1.根據(jù)熟悉的語(yǔ)言狡恬,談?wù)剝煞N語(yǔ)言的區(qū)別肪凛?
主要淺談下C/C++和PHP語(yǔ)言的區(qū)別:
1)PHP弱類型語(yǔ)言弊添,一種腳本語(yǔ)言泉沾,對(duì)數(shù)據(jù)的類型不要求過(guò)多何缓,較多的應(yīng)用于Web應(yīng)用開(kāi)發(fā)随橘,現(xiàn)在好多互聯(lián)網(wǎng)開(kāi)發(fā)公司的主流web后臺(tái)開(kāi)發(fā)語(yǔ)言腊瑟,主要框架為mvc模型聚假,如smarty,yaf,升級(jí)的PHP7速度較快闰非,對(duì)服務(wù)器的壓力要小很多膘格,在新浪微博已經(jīng)有應(yīng)用,對(duì)比很明顯财松。
2)C/C++開(kāi)發(fā)語(yǔ)言瘪贱,C語(yǔ)言更偏向硬件底層開(kāi)發(fā),C++語(yǔ)言是目前為止我認(rèn)為語(yǔ)法內(nèi)容最多的一種語(yǔ)言辆毡。C/C++在執(zhí)行速度上要快很多菜秦,畢竟其他類型的語(yǔ)言大都是C開(kāi)發(fā)的,更多應(yīng)用于網(wǎng)絡(luò)編程和嵌入式編程舶掖。
2.volatile是干啥用的球昨,(必須將cpu的寄存器緩存機(jī)制回答的很透徹),使用實(shí)例有哪些眨攘?(重點(diǎn))
1)訪問(wèn)寄存器比訪問(wèn)內(nèi)存單元要快,編譯器會(huì)優(yōu)化減少內(nèi)存的讀取主慰,可能會(huì)讀臟數(shù)據(jù)。聲明變量為volatile鲫售,編譯器不再對(duì)訪問(wèn)該變量的代碼優(yōu)化共螺,仍然從內(nèi)存讀取,使訪問(wèn)穩(wěn)定龟虎。
總結(jié):volatile關(guān)鍵詞影響編譯器編譯的結(jié)果璃谨,用volatile聲明的變量表示該變量隨時(shí)可能發(fā)生變化,與該變量有關(guān)的運(yùn)算,不再編譯優(yōu)化佳吞,以免出錯(cuò)拱雏。
2)使用實(shí)例如下(區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問(wèn)題。):
并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)
一個(gè)中斷服務(wù)子程序中會(huì)訪問(wèn)到的非自動(dòng)變量(Non-automatic variables)
多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量
3)一個(gè)參數(shù)既可以是const還可以是volatile嗎底扳?解釋為什么铸抑。
可以。一個(gè)例子是只讀的狀態(tài)寄存器衷模。它是volatile因?yàn)樗赡鼙灰庀氩坏降馗淖內笛础K莄onst因?yàn)槌绦虿粦?yīng)該試圖去修改它。
4)一個(gè)指針可以是volatile 嗎阱冶?解釋為什么刁憋。
可以。盡管這并不很常見(jiàn)木蹬。一個(gè)例子當(dāng)中斷服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)至耻。
下面的函數(shù)有什么錯(cuò)誤:
int square(volatile int *ptr) {
return *ptr * *ptr;
}
下面是答案:
這段代碼有點(diǎn)變態(tài)。這段代碼的目的是用來(lái)返指針ptr指向值的平方镊叁,但是尘颓,由于ptr指向一個(gè)volatile型參數(shù),編譯器將產(chǎn)生類似下面的代碼:
int square(volatile int *ptr){
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由于*ptr的值可能被意想不到地該變晦譬,因此a和b可能是不同的疤苹。結(jié)果,這段代碼可能返不是你所期望的平方值敛腌!正確的代碼如下:
long square(volatile int *ptr){
int a;
a = *ptr;
return a * a;
}
3.static const等等的用法卧土,(能說(shuō)出越多越好)(重點(diǎn))
2 首先說(shuō)說(shuō)const的用法(絕對(duì)不能說(shuō)是常數(shù))
1)在定義的時(shí)候必須進(jìn)行初始化
2)指針可以是const 指針,也可以是指向const對(duì)象的指針
3)定義為const的形參迎瞧,即在函數(shù)內(nèi)部是不能被修改的
4)類的成員函數(shù)可以被聲明為常成員函數(shù)夸溶,不能修改類的成員變量
5)類的成員函數(shù)可以返回的是常對(duì)象,即被const聲明的對(duì)象
6)類的成員變量是常成員變量不能在聲明時(shí)初始化凶硅,必須在構(gòu)造函數(shù)的列表里進(jìn)行初始化
(注:千萬(wàn)不要說(shuō)const是個(gè)常數(shù)缝裁,會(huì)被認(rèn)為是外行人的!W闵稹=莅蟆!哪怕說(shuō)個(gè)只讀也行)
下面的聲明都是什么意思氢妈?
const int a; a是一個(gè)常整型數(shù)
int const a; a是一個(gè)常整型數(shù)
const int *a; a是一個(gè)指向常整型數(shù)的指針粹污,整型數(shù)是不可修改的,但指針可以
int * const a; a為指向整型數(shù)的常指針首量,指針指向的整型數(shù)可以修改壮吩,但指針是不可修改的
int const * a const; a是一個(gè)指向常整型數(shù)的常指針进苍,指針指向的整型數(shù)是不可修改的,同時(shí)指針也是不可修改的
通過(guò)給優(yōu)化器一些附加的信息鸭叙,使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼觉啊。合理地使用關(guān)鍵字const可以使編譯器很自然地保護(hù)那些不希望被改變的參數(shù),防止其被無(wú)意的代碼修改沈贝。簡(jiǎn)而言之杠人,這樣可以減少bug的出現(xiàn)。
Const如何做到只讀宋下?
這些在編譯期間完成嗡善,對(duì)于內(nèi)置類型,如int学歧, 編譯器可能使用常數(shù)直接替換掉對(duì)此變量的引用罩引。而對(duì)于結(jié)構(gòu)體不一定。
2 再說(shuō)說(shuō)static的用法(三個(gè)明顯的作用一定要答出來(lái))
1)在函數(shù)體撩满,一個(gè)被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過(guò)程中維持其值不變蜒程。
2)在模塊內(nèi)(但在函數(shù)體外)绅你,一個(gè)被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問(wèn)伺帘,但不能被模塊外其它函數(shù)訪問(wèn)。它是一個(gè)本地的全局變量忌锯。
3)在模塊內(nèi)伪嫁,一個(gè)被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是偶垮,這個(gè)函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用
4)類內(nèi)的static成員變量屬于整個(gè)類所擁有张咳,不能在類內(nèi)進(jìn)行定義,只能在類的作用域內(nèi)進(jìn)行定義
5)類內(nèi)的static成員函數(shù)屬于整個(gè)類所擁有似舵,不能包含this指針脚猾,只能調(diào)用static成員函數(shù)
static全局變量與普通的全局變量有什么區(qū)別?static局部變量和普通局部變量有什么區(qū)別?static函數(shù)與普通函數(shù)有什么區(qū)別?
static全局變量與普通的全局變量有什么區(qū)別:static全局變量只初使化一次,防止在其他文件單元中被引用;
static局部變量和普通局部變量有什么區(qū)別:static局部變量只被初始化一次砚哗,下一次依據(jù)上一次結(jié)果值龙助;
static函數(shù)與普通函數(shù)有什么區(qū)別:static函數(shù)在內(nèi)存中只有一份,普通函數(shù)在每個(gè)被調(diào)用中維持一份拷貝
4.extern c 作用
告訴編譯器該段代碼以C語(yǔ)言進(jìn)行編譯蛛芥。
5.指針和引用的區(qū)別
1)引用是直接訪問(wèn)提鸟,指針是間接訪問(wèn)。
2)引用是變量的別名仅淑,本身不單獨(dú)分配自己的內(nèi)存空間称勋,而指針有自己的內(nèi)存空間
3)引用綁定內(nèi)存空間(必須賦初值),是一個(gè)變量別名不能更改綁定涯竟,可以改變對(duì)象的值赡鲜。
總的來(lái)說(shuō):引用既具有指針的效率空厌,又具有變量使用的方便性和直觀性
6. 關(guān)于靜態(tài)內(nèi)存分配和動(dòng)態(tài)內(nèi)存分配的區(qū)別及過(guò)程
靜態(tài)內(nèi)存分配是在編譯時(shí)完成的,不占用CPU資源银酬;動(dòng)態(tài)分配內(nèi)存運(yùn)行時(shí)完成蝇庭,分配與釋放需要占用CPU資源;
2)靜態(tài)內(nèi)存分配是在棧上分配的捡硅,動(dòng)態(tài)內(nèi)存是堆上分配的哮内;
3)動(dòng)態(tài)內(nèi)存分配需要指針或引用數(shù)據(jù)類型的支持,而靜態(tài)內(nèi)存分配不需要壮韭;
4)靜態(tài)內(nèi)存分配是按計(jì)劃分配北发,在編譯前確定內(nèi)存塊的大小,動(dòng)態(tài)內(nèi)存分配運(yùn)行時(shí)按需分配喷屋。
5)靜態(tài)分配內(nèi)存是把內(nèi)存的控制權(quán)交給了編譯器琳拨,動(dòng)態(tài)內(nèi)存把內(nèi)存的控制權(quán)交給了程序員;
6)靜態(tài)分配內(nèi)存的運(yùn)行效率要比動(dòng)態(tài)分配內(nèi)存的效率要高屯曹,因?yàn)閯?dòng)態(tài)內(nèi)存分配與釋放需要額外的開(kāi)銷狱庇;動(dòng)態(tài)內(nèi)存管理水平嚴(yán)重依賴于程序員的水平,處理不當(dāng)容易造成內(nèi)存泄漏恶耽。
7. 頭文件中的 ifndef/define/endif 干什么用密任?
預(yù)處理,防止頭文件被重復(fù)使用偷俭,包括pragma once都是這樣的
8. 宏定義求兩個(gè)元素的最小值
#define MIN(A,B) ((A) <= (B) ? (A) : (B))
9. 分別設(shè)置和清除一個(gè)整數(shù)的第三位浪讳?
#define BIT3 (0x1<<3)
static int a;
void set_bit3(void){
? ? a |= BIT3;
}
void clear_bit3(void){
? ? a &= ~BIT3;
}
10. 用預(yù)處理指令#define 聲明一個(gè)常數(shù),用以表明1年中有多少秒
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
關(guān)于面試涌萤,關(guān)于技術(shù)淹遵,需要溝通交流點(diǎn)這里。
面試负溪,技術(shù)透揣,崗位信息全網(wǎng)覆蓋中~
一切只為渴望更優(yōu)秀的自己!
11. 預(yù)處理器標(biāo)識(shí)#error的目的是什么川抡?
拋出錯(cuò)誤提示辐真,標(biāo)識(shí)外部宏是否被定義!
12. 嵌入式系統(tǒng)中經(jīng)常要用到無(wú)限循環(huán),你怎么樣用C編寫死循環(huán)呢猖腕?
記住這是第一方案2鹌怼!L雀小放坏!
while(1)
{
}
一些程序員更喜歡如下方案:
for(; {
}
匯編語(yǔ)言的無(wú)線循環(huán)是:
Loop:
…
goto Loop;
13. 用變量a給出下面的定義
一個(gè)有10個(gè)指針的數(shù)組,該指針指向一個(gè)函數(shù)老玛,該函數(shù)有一個(gè)整型參數(shù)并返回一個(gè)整型數(shù) int (*a[10])(int);
14. 中斷是嵌入式系統(tǒng)中重要的組成部分淤年,這導(dǎo)致了很多編譯開(kāi)發(fā)商提供一種擴(kuò)展—讓標(biāo)準(zhǔn)C支持中斷钧敞。具代表事實(shí)是,產(chǎn)生了一個(gè)新的關(guān)鍵字 __interrupt
16. memcpy函數(shù)的實(shí)現(xiàn)
void *memcpy(void *dest, const void *src, size_t count) {
char *tmp = dest;
const char *s = src;
while (count--)
? *tmp++ = *s++;
? return dest;
}
17. Strcpy函數(shù)實(shí)現(xiàn)
char *strcpy(char *dst,const char *src) {
? ? ? assert(dst != NULL && src != NULL);
? ? ? char *ret = dst;
? ? ? while((* dst++ = * src++) != '\0') ;
? ? ? return ret;
}
18. strcat函數(shù)的實(shí)現(xiàn)
char *strcat(char *strDes, const char *strSrc){
assert((strDes != NULL) && (strSrc != NULL));
char *address = strDes;
while (*strDes != ‘\0′)
++ strDes;
while ((*strDes ++ = *strSrc ++) != ‘\0′)
return address;
}
19.strncat實(shí)現(xiàn)
char *strncat(char *strDes, const char *strSrc, int count){
assert((strDes != NULL) && (strSrc != NULL));
char *address = strDes;
while (*strDes != ‘\0′)
++ strDes;
while (count — && *strSrc != ‘\0′ )
*strDes ++ = *strSrc ++;
*strDes = ‘\0′;
return address;
}
20. strcmp函數(shù)實(shí)現(xiàn)
int strcmp(const char *str1,const char *str2){
? ? /*不可用while(*str1++==*str2++)來(lái)比較麸粮,當(dāng)不相等時(shí)仍會(huì)執(zhí)行一次++溉苛,
? ? return返回的比較值實(shí)際上是下一個(gè)字符堵第。應(yīng)將++放到循環(huán)體中進(jìn)行贿堰。*/
? ? while(*str1 == *str2){
? ? ? ? if(*str1 == '\0')
? ? ? ? ? ? return0;
? ? ? ? ++str1;
? ? ? ? ++str2;
? ? }
? ? return *str1 - *str2;
}
21. strncmp實(shí)現(xiàn)
int strncmp(const char *s, const char *t, int count){
? ? assert((s != NULL) && (t != NULL));
? ? while (*s && *t && *s == *t && count –) {
? ? ? ? ++ s;
? ? ? ? ++ t;
? ? }
? ? return (*s – *t);
}
22.strlen函數(shù)實(shí)現(xiàn)
int strlen(const char *str){
? ? assert(str != NULL);
? ? int len = 0;
? ? while (*str ++ != ‘\0′)
? ? ? ? ++ len;
? ? return len;
}
23. strpbrk函數(shù)實(shí)現(xiàn)
char * strpbrk(const char * cs,const char * ct){
? ? const char *sc1,*sc2;
? ? for( sc1 = cs; *sc1 != '\0'; ++sc1){
? ? ? ? for( sc2 = ct; *sc2 != '\0'; ++sc2){
? ? ? ? ? ? if (*sc1 == *sc2){
? ? ? ? ? ? ? ? return (char *) sc1;
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? return NULL;
}
24. strstr函數(shù)實(shí)現(xiàn)
char *strstr(const char *s1,const char *s2){
int len2;
if(!(len2=strlen(s2)))//此種情況下s2不能指向空,否則strlen無(wú)法測(cè)出長(zhǎng)度氯檐,這條語(yǔ)句錯(cuò)誤
return(char*)s1;
for(;*s1;++s1)
{
? ? if(*s1==*s2 && strncmp(s1,s2,len2)==0)
? ? return(char*)s1;
}
return NULL;
}
25. string實(shí)現(xiàn)(注意:賦值構(gòu)造齐遵,operator=是關(guān)鍵)
class String{
public:
//普通構(gòu)造函數(shù)
String(const char *str = NULL);
//拷貝構(gòu)造函數(shù)
String(const String &other);
//賦值函數(shù)
String & operator=(String &other) ;
//析構(gòu)函數(shù)
~String(void);
private:
char* m_str;
};
分別實(shí)現(xiàn)以上四個(gè)函數(shù)
//普通構(gòu)造函數(shù)
String::String(const char* str){
? ? if(str==NULL) //如果str為NULL寂玲,存空字符串{
? ? ? ? m_str = new char[1]; //分配一個(gè)字節(jié)
? ? ? ? *m_str = ‘\0′; //賦一個(gè)’\0′
}else{
? ? ? str = new char[strlen(str) + 1];//分配空間容納str內(nèi)容
? ? ? ? strcpy(m_str, str); //復(fù)制str到私有成員m_str中
? ? }
}
//析構(gòu)函數(shù)
String::~String(){
? ? if(m_str!=NULL) //如果m_str不為NULL,釋放堆內(nèi)存{
? ? ? ? delete [] m_str;
? ? ? ? m_str = NULL;
}
}
//拷貝構(gòu)造函數(shù)
String::String(const String &other){
? ? m_str = new char[strlen(other.m_str)+1]; //分配空間容納str內(nèi)容
? ? strcpy(m_str, other.m_str); //復(fù)制other.m_str到私有成員m_str中
}
//賦值函數(shù)
String & String::operator=(String &other){
? ? if(this == &other) //若對(duì)象與other是同一個(gè)對(duì)象梗摇,直接返回本{
? ? ? ? return *this
}
? ? delete [] m_str; //否則拓哟,先釋放當(dāng)前對(duì)象堆內(nèi)存
? ? m_str = new char[strlen(other.m_str)+1]; //分配空間容納str內(nèi)容
? ? strcpy(m_str, other.m_str); //復(fù)制other.m_str到私有成員m_str中
? ? return *this;
}
26. C語(yǔ)言同意一些令人震驚的結(jié)構(gòu),下面的結(jié)構(gòu)是合法的嗎伶授,如果是它做些什么断序?
int a = 5, b = 7, c;
c = a+++b; 等同于 c = a++ + b;
因此, 這段代碼持行后a = 6, b = 7, c = 12。
27. 用struct關(guān)鍵字與class關(guān)鍵定義類以及繼承的區(qū)別
(1)定義類差別
struct關(guān)鍵字也可以實(shí)現(xiàn)類糜烹,用class和struct關(guān)鍵字定義類的唯一差別在于默認(rèn)訪問(wèn)級(jí)別:默認(rèn)情況下违诗,struct成員的訪問(wèn)級(jí)別為public,而class成員的為private景图。語(yǔ)法使用也相同较雕,直接將class改為struct即可。
(2)繼承差別
使用class保留字的派生類默認(rèn)具有private繼承挚币,而用struct保留字定義的類某人具有public繼承。其它則沒(méi)有任何區(qū)別扣典。
主要點(diǎn)就兩個(gè):默認(rèn)的訪問(wèn)級(jí)別和默認(rèn)的繼承級(jí)別 class都是private
28.派生類與虛函數(shù)概述
(1) 派生類繼承的函數(shù)不能定義為虛函數(shù)妆毕。虛函數(shù)是希望派生類重新定義。如果派生類沒(méi)有重新定義某個(gè)虛函數(shù)贮尖,則在調(diào)用的時(shí)候會(huì)使用基類中定義的版本笛粘。
(2)派生類中函數(shù)的聲明必須與基類中定義的方式完全匹配。
(3) 基類中聲明為虛函數(shù)湿硝,則派生類也為虛函數(shù)薪前。
29. 虛函數(shù)與純虛函數(shù)區(qū)別
1)虛函數(shù)在子類里面也可以不重載的;但純虛必須在子類去實(shí)現(xiàn)
2)帶純虛函數(shù)的類叫虛基類也叫抽象類关斜,這種基類不能直接生成對(duì)象示括,只能被繼承,重寫虛函數(shù)后才能使用痢畜,運(yùn)行時(shí)動(dòng)態(tài)動(dòng)態(tài)綁定垛膝!
30.深拷貝與淺拷貝
淺拷貝:
char ori[]=“hello”鳍侣;char *copy=ori;
深拷貝:
char ori[]=“hello”; char *copy=new char[]; copy=ori;
淺拷貝只是對(duì)指針的拷貝吼拥,拷貝后兩個(gè)指針指向同一個(gè)內(nèi)存空間倚聚,深拷貝不但對(duì)指針進(jìn)行拷貝,而且對(duì)指針指向的內(nèi)容進(jìn)行拷貝凿可,經(jīng)深拷貝后的指針是指向兩個(gè)不同地址的指針惑折。
淺拷貝可能出現(xiàn)的問(wèn)題:
1) 淺拷貝只是拷貝了指針,使得兩個(gè)指針指向同一個(gè)地址枯跑,這樣在對(duì)象塊結(jié)束唬复,調(diào)用函數(shù)析構(gòu)的時(shí),會(huì)造成同一份資源析構(gòu)2次全肮,即delete同一塊內(nèi)存2次敞咧,造成程序崩潰。
2) 淺拷貝使得兩個(gè)指針都指向同一塊內(nèi)存辜腺,任何一方的變動(dòng)都會(huì)影響到另一方休建。
3) 同一個(gè)空間,第二次釋放失敗评疗,導(dǎo)致無(wú)法操作該空間测砂,造成內(nèi)存泄漏。
31. stl各容器的實(shí)現(xiàn)原理(必考)
Vector順序容器百匆,是一個(gè)動(dòng)態(tài)數(shù)組砌些,支持隨機(jī)插入、刪除加匈、查找等操作存璃,在內(nèi)存中是一塊連續(xù)的空間。在原有空間不夠情況下自動(dòng)分配空間雕拼,增加為原來(lái)的兩倍纵东。vector隨機(jī)存取效率高,但是在vector插入元素啥寇,需要移動(dòng)的數(shù)目多偎球,效率低下。
注:vector動(dòng)態(tài)增加大小時(shí)是以原大小的兩倍另外配置一塊較大的空間辑甜,然后將原內(nèi)容拷貝過(guò)來(lái)衰絮,然后才開(kāi)始在原內(nèi)容之后構(gòu)造新元素,并釋放原空間磷醋。因此猫牡,對(duì)vector空間重新配置,指向原vector的所有迭代器就都失效了子檀。
Map關(guān)聯(lián)容器镊掖,以鍵值對(duì)的形式進(jìn)行存儲(chǔ)乃戈,方便進(jìn)行查找。關(guān)鍵詞起到索引的作用亩进,值則表示與索引相關(guān)聯(lián)的數(shù)據(jù)症虑。紅黑樹(shù)的結(jié)構(gòu)實(shí)現(xiàn),插入刪除等操作都在O(logn)時(shí)間內(nèi)完成归薛。
Set是關(guān)聯(lián)容器谍憔,set每個(gè)元素只包含一個(gè)關(guān)鍵字。set支持高效的關(guān)鍵字檢查是否在set中主籍。set也是以紅黑樹(shù)的結(jié)構(gòu)實(shí)現(xiàn)习贫,支持高效插入、刪除等操作千元。
32.哪些庫(kù)函數(shù)屬于高危函數(shù)苫昌,為什么?
strcpy 賦值到目標(biāo)區(qū)間可能會(huì)造成緩沖區(qū)溢出幸海!
33.STL有7種主要容器:vector,list,deque,map,multimap,set,multiset
34.你如何理解MVC祟身。簡(jiǎn)單舉例來(lái)說(shuō)明其應(yīng)用。
MVC模式是observer 模式的一個(gè)特例,現(xiàn)在很多都是java的一些框架物独,MFC的袜硫,PHP的。
35.C++特點(diǎn)是什么挡篓,多態(tài)實(shí)現(xiàn)機(jī)制婉陷?(面試問(wèn)過(guò))多態(tài)作用??jī)蓚€(gè)必要條件官研?
C++中多態(tài)機(jī)制主要體現(xiàn)在兩個(gè)方面秽澳,一個(gè)是函數(shù)的重載,一個(gè)是接口的重寫阀参。接口多態(tài)指的是“一個(gè)接口多種形態(tài)”肝集。每一個(gè)對(duì)象內(nèi)部都有一個(gè)虛表指針,該虛表指針被初始化為本類的虛表蛛壳。所以在程序中,不管你的對(duì)象類型如何轉(zhuǎn)換所刀,但該對(duì)象內(nèi)部的虛表指針是固定的衙荐,所以呢,才能實(shí)現(xiàn)動(dòng)態(tài)的對(duì)象函數(shù)調(diào)用浮创,這就是C++多態(tài)性實(shí)現(xiàn)的原理忧吟。
多態(tài)的基礎(chǔ)是繼承,需要虛函數(shù)的支持斩披,簡(jiǎn)單的多態(tài)是很簡(jiǎn)單的溜族。子類繼承父類大部分的資源讹俊,不能繼承的有構(gòu)造函數(shù),析構(gòu)函數(shù)煌抒,拷貝構(gòu)造函數(shù)仍劈,operator=函數(shù),友元函數(shù)等等
作用:
隱藏實(shí)現(xiàn)細(xì)節(jié)寡壮,代碼能夠模塊化贩疙;2. 接口重用:為了類在繼承和派生的時(shí)候正確調(diào)用。
必要條件:
一個(gè)基類的指針或者引用指向派生類的對(duì)象况既;2.虛函數(shù)
36. 多重繼承有什么問(wèn)題? 怎樣消除多重繼承中的二義性?
1)增加程序的復(fù)雜度这溅,使程序的編寫和維護(hù)比較困難,容易出錯(cuò)棒仍;
2)繼承類和基類的同名函數(shù)產(chǎn)生了二義性悲靴,同名函數(shù)不知道調(diào)用基類還是繼承類,C++中使用虛函數(shù)解決這個(gè)問(wèn)題
3)繼承過(guò)程中可能會(huì)繼承一些不必要的數(shù)據(jù)莫其,對(duì)于多級(jí)繼承癞尚,可能會(huì)產(chǎn)生數(shù)據(jù)很長(zhǎng)
可以使用成員限定符和虛函數(shù)解決多重繼承中函數(shù)的二義性問(wèn)題。
37.求兩個(gè)數(shù)的乘積和商數(shù)榜配,該作用由宏定義來(lái)實(shí)現(xiàn)
#define product(a,b) ((a)*(b))
#define divide(a,b) ((a)/(b))
38.什么叫靜態(tài)關(guān)聯(lián)否纬,什么叫動(dòng)態(tài)關(guān)聯(lián)
多態(tài)中,靜態(tài)關(guān)聯(lián)是程序在編譯階段就能確定實(shí)際執(zhí)行動(dòng)作蛋褥,程序運(yùn)行才能確定叫動(dòng)態(tài)關(guān)聯(lián)
39.什么叫智能指針?常用的智能指針有哪些临燃?智能指針的實(shí)現(xiàn)?
智能指針是一個(gè)存儲(chǔ)指向動(dòng)態(tài)分配(堆)對(duì)象指針的類烙心,構(gòu)造函數(shù)傳入普通指針膜廊,析構(gòu)函數(shù)釋放指針。棧上分配淫茵,函數(shù)或程序結(jié)束自動(dòng)釋放爪瓜,防止內(nèi)存泄露。使用引用計(jì)數(shù)器匙瘪,類與指向的對(duì)象相關(guān)聯(lián)铆铆,引用計(jì)數(shù)跟蹤該類有多少個(gè)對(duì)象共享同一指針。創(chuàng)建類的新對(duì)象時(shí)丹喻,初始化指針并將引用計(jì)數(shù)置為1薄货;當(dāng)對(duì)象作為另一對(duì)象的副本而創(chuàng)建,增加引用計(jì)數(shù)碍论;對(duì)一個(gè)對(duì)象進(jìn)行賦值時(shí)谅猾,減少引用計(jì)數(shù),并增加右操作數(shù)所指對(duì)象的引用計(jì)數(shù);調(diào)用析構(gòu)函數(shù)時(shí)税娜,構(gòu)造函數(shù)減少引用計(jì)數(shù)坐搔,當(dāng)引用計(jì)數(shù)減至0,則刪除基礎(chǔ)對(duì)象敬矩。
std::auto_ptr概行,不支持復(fù)制(拷貝構(gòu)造函數(shù))和賦值(operator =),編譯不會(huì)提示出錯(cuò)谤绳。
C++11引入的unique_ptr占锯, 也不支持復(fù)制和賦值,但比auto_ptr好缩筛,直接賦值會(huì)編譯出錯(cuò)消略。
C++11或boost的shared_ptr,基于引用計(jì)數(shù)的智能指針瞎抛∫昭荩可隨意賦值,直到內(nèi)存的引用計(jì)數(shù)為0的時(shí)候這個(gè)內(nèi)存會(huì)被釋放桐臊。還有Weak_ptr
40.枚舉與#define 宏的區(qū)別
1)#define 宏常量是在預(yù)編譯階段進(jìn)行簡(jiǎn)單替換胎撤。枚舉常量則是在編譯的時(shí)候確定其值。
2)可以調(diào)試枚舉常量断凶,但是不能調(diào)試宏常量伤提。
3)枚舉可以一次定義大量相關(guān)的常量,而#define 宏一次只能定義一個(gè)认烁。
41.介紹一下函數(shù)的重載
重載是在不同類型上作不同運(yùn)算而又用同樣的名字的函數(shù)肿男。重載函數(shù)至少在參數(shù)個(gè)數(shù),參數(shù)類型却嗡, 或參數(shù)順序上有所不同舶沛。
42.派生新類的過(guò)程要經(jīng)歷三個(gè)步驟
1.吸收基類成員 2.改造基類成員 3.添加新成員
43.面向?qū)ο蟮娜齻€(gè)基本特征,并簡(jiǎn)單敘述之?
1)封裝:將客觀事物抽象成類窗价,每個(gè)類對(duì)自身的數(shù)據(jù)和方法實(shí)行2)繼承3)多態(tài):允許一個(gè)基類的指針或引用指向一個(gè)派生類對(duì)象
44.多態(tài)性體現(xiàn)都有哪些如庭?動(dòng)態(tài)綁定怎么實(shí)現(xiàn)?
多態(tài)性是一個(gè)接口,多種實(shí)現(xiàn)撼港,是面向?qū)ο蟮暮诵摹?編譯時(shí)多態(tài)性:通過(guò)重載函數(shù)實(shí)現(xiàn)坪它。運(yùn)行時(shí)多態(tài)性:通過(guò)虛函數(shù)實(shí)現(xiàn),結(jié)合動(dòng)態(tài)綁定。
45.虛函數(shù)帝牡,虛函數(shù)表里面內(nèi)存如何分配哟楷?
編譯時(shí)若基類中有虛函數(shù),編譯器為該的類創(chuàng)建一個(gè)一維數(shù)組的虛表否灾,存放是每個(gè)虛函數(shù)的地址∶迹基類和派生類都包含虛函數(shù)時(shí)墨技,這兩個(gè)類都建立一個(gè)虛表惩阶。構(gòu)造函數(shù)中進(jìn)行虛表的創(chuàng)建和虛表指針的初始化。在構(gòu)造子類對(duì)象時(shí)扣汪,要先調(diào)用父類的構(gòu)造函數(shù)断楷,初始化父類對(duì)象的虛表指針,該虛表指針指向父類的虛表崭别。執(zhí)行子類的構(gòu)造函數(shù)時(shí)冬筒,子類對(duì)象的虛表指針被初始化,指向自身的虛表茅主。每一個(gè)類都有虛表舞痰。虛表可以繼承,如果子類沒(méi)有重寫虛函數(shù)诀姚,那么子類虛表中仍然會(huì)有該函數(shù)的地址响牛,只不過(guò)這個(gè)地址指向的是基類的虛函數(shù)實(shí)現(xiàn)。派生類的虛表中虛函數(shù)地址的排列順序和基類的虛表中虛函數(shù)地址排列順序相同赫段。當(dāng)用一個(gè)指針/引用調(diào)用一個(gè)函數(shù)的時(shí)候呀打,被調(diào)用的函數(shù)是取決于這個(gè)指針/引用的類型。即如果這個(gè)指針/引用是基類對(duì)象的指針/引用就調(diào)用基類的方法糯笙;如果指針/引用是派生類對(duì)象的指針/引用就調(diào)用派生類的方法贬丛,當(dāng)然如果派生類中沒(méi)有此方法,就會(huì)向上到基類里面去尋找相應(yīng)的方法给涕。這些調(diào)用在編譯階段就確定了豺憔。當(dāng)涉及到多態(tài)性的時(shí)候,采用了虛函數(shù)和動(dòng)態(tài)綁定稠炬,此時(shí)的調(diào)用就不會(huì)在編譯時(shí)候確定而是在運(yùn)行時(shí)確定焕阿。不在單獨(dú)考慮指針/引用的類型而是看指針/引用的對(duì)象的類型來(lái)判斷函數(shù)的調(diào)用,根據(jù)對(duì)象中虛指針指向的虛表中的函數(shù)的地址來(lái)確定調(diào)用哪個(gè)函數(shù)首启。
46. 純虛函數(shù)如何定義暮屡?含有純虛函數(shù)的類稱為什么?為什么析構(gòu)函數(shù)要定義成虛函數(shù)毅桃?
純虛函數(shù)是在基類中聲明的虛函數(shù)褒纲,它在基類中沒(méi)有定義,但要求任何派生類都要定義自己的實(shí)現(xiàn)方法钥飞。純虛函數(shù)是虛函數(shù)再加上= 0莺掠。virtual void fun ()=0。含有純虛函數(shù)的類稱為抽象類在很多情況下读宙,基類本身生成對(duì)象是不合情理的彻秆。例如,動(dòng)物作為一個(gè)基類可以派生出老虎、孔雀等子類唇兑,但動(dòng)物本身生成對(duì)象明顯不合常理酒朵。同時(shí)含有純虛擬函數(shù)的類稱為抽象類,它不能生成對(duì)象扎附。如果析構(gòu)函數(shù)不是虛函數(shù)蔫耽,那么釋放內(nèi)存時(shí)候,編譯器會(huì)使用靜態(tài)聯(lián)編留夜,認(rèn)為p就是一個(gè)基類指針匙铡,調(diào)用基類析構(gòu)函數(shù),這樣子類對(duì)象的內(nèi)存沒(méi)有釋放碍粥,造成內(nèi)存泄漏鳖眼。定義成虛函數(shù)以后,就會(huì)動(dòng)態(tài)聯(lián)編即纲,先調(diào)用子類析構(gòu)函數(shù)具帮,再基類。
47. C++中哪些不能是虛函數(shù)低斋?
1)普通函數(shù)只能重載蜂厅,不能被重寫,因此編譯器會(huì)在編譯時(shí)綁定函數(shù)膊畴。
2)構(gòu)造函數(shù)是知道全部信息才能創(chuàng)建對(duì)象掘猿,然而虛函數(shù)允許只知道部分信息。
3)內(nèi)聯(lián)函數(shù)在編譯時(shí)被展開(kāi)唇跨,虛函數(shù)在運(yùn)行時(shí)才能動(dòng)態(tài)綁定函數(shù)稠通。
4)友元函數(shù) 因?yàn)椴豢梢员焕^承。
5)靜態(tài)成員函數(shù) 只有一個(gè)實(shí)體买猖,不能被繼承改橘。父類和子類共有。
48. 類型轉(zhuǎn)換有哪些玉控?各適用什么環(huán)境飞主?dynamic_cast轉(zhuǎn)換失敗時(shí),會(huì)出現(xiàn)什么情況(對(duì)指針高诺,返回NULL.對(duì)引用碌识,拋出bad_cast異常)?
靜態(tài)類型轉(zhuǎn)換虱而,static_cast筏餐,基本類型之間和具有繼承關(guān)系的類型。
例子A,double類型轉(zhuǎn)換成int牡拇。B,將子類對(duì)象轉(zhuǎn)換成基類對(duì)象魁瞪。
常量類型轉(zhuǎn)換穆律,const_cast, 去除指針變量的常量屬性。
無(wú)法將非指針的常量轉(zhuǎn)換為普通變量佩番。
動(dòng)態(tài)類型轉(zhuǎn)換众旗,dynamic_cast,運(yùn)行時(shí)進(jìn)行轉(zhuǎn)換分析的趟畏,并非在編譯時(shí)進(jìn)行。dynamic_cast轉(zhuǎn)換符只能用于含有虛函數(shù)的類滩租。dynamic_cast用于類層次間的向上轉(zhuǎn)換和向下轉(zhuǎn)換赋秀,還可以用于類間的交叉轉(zhuǎn)換。在類層次間進(jìn)行向上轉(zhuǎn)換律想,即子類轉(zhuǎn)換為父類猎莲,此時(shí)完成的功能和static_cast是相同的,因?yàn)榫幾g器默認(rèn)向上轉(zhuǎn)換總是安全的技即。向下轉(zhuǎn)換時(shí)著洼,dynamic_cast具有類型檢查的功能,更加安全而叼。類間的交叉轉(zhuǎn)換指的是子類的多個(gè)父類之間指針或引用的轉(zhuǎn)換身笤。該函數(shù)只能在繼承類對(duì)象的指針之間或引用之間進(jìn)行類型轉(zhuǎn)換,或者有虛函數(shù)的類葵陵。
49. 如何判斷一段程序是由C 編譯程序還是由C++編譯程序編譯的液荸?
#ifdef __cplusplus
cout<<“C++”;
#else
cout<<“c”;
#endif
50. 為什么要用static_cast轉(zhuǎn)換而不用c語(yǔ)言中的轉(zhuǎn)換?
Static_cast轉(zhuǎn)換脱篙,它會(huì)檢查類型看是否能轉(zhuǎn)換娇钱,有類型安全檢查。
比如绊困,這個(gè)在C++中合法文搂,但是確實(shí)錯(cuò)誤的。
A* a= new A;
B* b = (B*)a;
51. 操作符重載(+操作符)秤朗,具體如何去定義煤蹭?
除了類屬關(guān)系運(yùn)算符”.”、成員指針運(yùn)算符”.*”川梅、作用域運(yùn)算符”::”疯兼、sizeof運(yùn)算符和三目運(yùn)算符”?:”以外,C++中的所有運(yùn)算符都可以重載贫途。
<返回類型說(shuō)明符> operator <運(yùn)算符符號(hào)>(<參數(shù)表>){}
重載為類的成員函數(shù)和重載為類的非成員函數(shù)吧彪。參數(shù)個(gè)數(shù)會(huì)不同,應(yīng)為this指針丢早。
52. 內(nèi)存對(duì)齊的原則姨裸?
A.結(jié)構(gòu)體的大小為最大成員的整數(shù)倍秧倾。
B.成員首地址的偏移量為其類型大小整數(shù)倍。
53. 內(nèi)聯(lián)函數(shù)與宏定義的區(qū)別傀缩?
內(nèi)聯(lián)函數(shù)是用來(lái)消除函數(shù)調(diào)用時(shí)的時(shí)間開(kāi)銷那先。頻繁被調(diào)用的短小函數(shù)非常受益。
A. 宏定義不檢查函數(shù)參數(shù)赡艰,返回值什么的售淡,只是展開(kāi),相對(duì)來(lái)說(shuō)慷垮,內(nèi)聯(lián)函數(shù)會(huì)檢查參數(shù)類型揖闸,所以更安全。
B. 宏是由預(yù)處理器對(duì)宏進(jìn)行替代料身,而內(nèi)聯(lián)函數(shù)是通過(guò)編譯器控制來(lái)實(shí)現(xiàn)的
54. 動(dòng)態(tài)分配對(duì)象和靜態(tài)分配對(duì)象的區(qū)別汤纸?
動(dòng)態(tài)分配就是用運(yùn)算符new來(lái)創(chuàng)建一個(gè)類的對(duì)象,在堆上分配內(nèi)存芹血。
靜態(tài)分配就是A a;這樣來(lái)由編譯器來(lái)創(chuàng)建一個(gè)對(duì)象贮泞,在棧上分配內(nèi)存。
55. explicit是干什么用的 ?
構(gòu)造器 幔烛,可以阻止不應(yīng)該允許的經(jīng)過(guò)轉(zhuǎn)換構(gòu)造函數(shù)進(jìn)行的隱式轉(zhuǎn)換的發(fā)生啃擦。explicit是用來(lái)防止外部非正規(guī)的拷貝構(gòu)造的邓嘹,要想不存在傳值的隱式轉(zhuǎn)換問(wèn)題镜盯。
56. 內(nèi)存溢出有那些因素棵逊?
(1) 使用非類型安全(non-type-safe)的語(yǔ)言如 C/C++ 等耕驰。
(2) 以不可靠的方式存取或者復(fù)制內(nèi)存緩沖區(qū)仍稀。
(3) 編譯器設(shè)置的內(nèi)存緩沖區(qū)太靠近關(guān)鍵數(shù)據(jù)結(jié)構(gòu)籽孙。
57. new與malloc的區(qū)別亲善,delete和free的區(qū)別凉袱?
1.malloc/free是C/C++語(yǔ)言的標(biāo)準(zhǔn)庫(kù)函數(shù)傲宜,new/delete是C++的運(yùn)算符
2.new能夠自動(dòng)分配空間大小运杭,malloc傳入?yún)?shù)。
3. new/delete能進(jìn)行對(duì)對(duì)象進(jìn)行構(gòu)造和析構(gòu)函數(shù)的調(diào)用進(jìn)而對(duì)內(nèi)存進(jìn)行更加詳細(xì)的工作函卒,而malloc/free不能辆憔。
既然new/delete的功能完全覆蓋了malloc/free,為什么C++還保留malloc/free呢报嵌?因?yàn)镃++程序經(jīng)常要調(diào)用C函數(shù)虱咧,而C程序只能用malloc/free管理動(dòng)態(tài)內(nèi)存。
58. 必須使用初始化列表初始化數(shù)據(jù)成員的情況
1.是對(duì)象的情況锚国;
2.const修飾的類成員腕巡;
3.引用成員數(shù)據(jù);
類成員變量的初始化不是按照初始化表順序被初始化血筑,是按照在類中聲明的順序被初始化的绘沉。
59.深入談?wù)劧押蜅?/b>
1).分配和管理方式不同 :
堆是動(dòng)態(tài)分配的煎楣,其空間的分配和釋放都由程序員控制。
棧由編譯器自動(dòng)管理车伞。棧有兩種分配方式:靜態(tài)分配和動(dòng)態(tài)分配择懂。靜態(tài)分配由編譯器完成,比如局部變量的分配另玖。動(dòng)態(tài)分配由alloca()函數(shù)進(jìn)行分配困曙,但是棧的動(dòng)態(tài)分配和堆是不同的,它的動(dòng)態(tài)分配是由編譯器進(jìn)行釋放日矫,無(wú)須手工控制赂弓。
2).產(chǎn)生碎片不同
對(duì)堆來(lái)說(shuō),頻繁的new/delete或者malloc/free勢(shì)必會(huì)造成內(nèi)存空間的不連續(xù)哪轿,造成大量的碎片,使程序效率降低翔怎。
對(duì)棧而言窃诉,則不存在碎片問(wèn)題,因?yàn)闂J窍冗M(jìn)后出的隊(duì)列赤套,永遠(yuǎn)不可能有一個(gè)內(nèi)存塊從棧中間彈出飘痛。
3).生長(zhǎng)方向不同
堆是向著內(nèi)存地址增加的方向增長(zhǎng)的,從內(nèi)存的低地址向高地址方向增長(zhǎng)容握。
棧是向著內(nèi)存地址減小的方向增長(zhǎng)宣脉,由內(nèi)存的高地址向低地址方向增長(zhǎng)。
60.內(nèi)存的靜態(tài)分配和動(dòng)態(tài)分配的區(qū)別剔氏?
時(shí)間不同塑猖。靜態(tài)分配發(fā)生在程序編譯和連接時(shí)。動(dòng)態(tài)分配則發(fā)生在程序調(diào)入和執(zhí)行時(shí)谈跛。
空間不同羊苟。堆都是動(dòng)態(tài)分配的,沒(méi)有靜態(tài)分配的堆感憾。棧有2種分配方式:靜態(tài)分配和動(dòng)態(tài)分配蜡励。靜態(tài)分配是編譯器完成的,比如局部變量的分配阻桅。alloca凉倚,可以從棧里動(dòng)態(tài)分配內(nèi)存,不用擔(dān)心內(nèi)存泄露問(wèn)題嫂沉,當(dāng)函數(shù)返回時(shí)稽寒,通過(guò)alloca申請(qǐng)的內(nèi)存就會(huì)被自動(dòng)釋放掉。
61. 模版怎么實(shí)現(xiàn)输瓜?模版作用瓦胎?
實(shí)現(xiàn):template void swap(T& a, T& b){}
作用:將算法與具體對(duì)象分離芬萍,與類型無(wú)關(guān),通用搔啊,節(jié)省精力
62. 多重類構(gòu)造和析構(gòu)的順序
記住析構(gòu)函數(shù)的調(diào)用順序與構(gòu)造函數(shù)是相反的柬祠。
63. 迭代器刪除元素的會(huì)發(fā)生什么?
迭代器失效
64. 靜態(tài)成員函數(shù)和數(shù)據(jù)成員有什么意義负芋?
1)非靜態(tài)數(shù)據(jù)成員漫蛔,每個(gè)對(duì)象都有自己的拷貝。而靜態(tài)數(shù)據(jù)成員被當(dāng)作是類的成員旧蛾,是該類的所有對(duì)象所共有的莽龟,在程序中只分配一次內(nèi)存只有一份拷貝,所以對(duì)象都共享锨天,值對(duì)每個(gè)對(duì)象都是一樣的毯盈,它的值可以更新。
2)靜態(tài)數(shù)據(jù)成員存儲(chǔ)在全局?jǐn)?shù)據(jù)區(qū)病袄,所以不能在類聲明中定義搂赋,應(yīng)該在類外定義。由于它不屬于特定的類對(duì)象益缠,在沒(méi)有產(chǎn)生類對(duì)象時(shí)作用域就可見(jiàn)脑奠,即在沒(méi)有產(chǎn)生類的實(shí)例時(shí),我們就可以操作它幅慌。
3)靜態(tài)成員函數(shù)與靜態(tài)數(shù)據(jù)成員一樣宋欺,都是在類的內(nèi)部實(shí)現(xiàn),屬于類定義的一部分胰伍。因?yàn)槠胀ǔ蓡T函數(shù)總是具體的屬于具體對(duì)象的齿诞,每個(gè)有this指針。靜態(tài)成員函數(shù)沒(méi)有this指針喇辽,它無(wú)法訪問(wèn)屬于類對(duì)象的非靜態(tài)數(shù)據(jù)成員掌挚,也無(wú)法訪問(wèn)非靜態(tài)成員函數(shù)。靜態(tài)成員之間可以互相訪問(wèn)菩咨,包括靜態(tài)成員函數(shù)訪問(wèn)靜態(tài)數(shù)據(jù)成員和訪問(wèn)靜態(tài)成員函數(shù)吠式;
4)非靜態(tài)成員函數(shù)可以任意地訪問(wèn)靜態(tài)成員函數(shù)和靜態(tài)數(shù)據(jù)成員;
5)沒(méi)有this指針的額外開(kāi)銷抽米,靜態(tài)成員函數(shù)與類的全局函數(shù)相比特占,速度上會(huì)有少許的增長(zhǎng);
6)調(diào)用靜態(tài)成員函數(shù)云茸,可以用成員訪問(wèn)操作符(.)和(->)為一個(gè)類的對(duì)象或指向類對(duì)象的指調(diào)用靜態(tài)成員函數(shù)是目。
66請(qǐng)用C/C++實(shí)現(xiàn)字符串反轉(zhuǎn)(不調(diào)用庫(kù)函數(shù))”abc”類型的
char *reverse_str(char *str) {
? ? if(NULL == str) { //字符串為空直接返回
? ? ? ? return str;
? ? }
? ? char *begin;
? ? char *end;
? ? begin = end = str;
? ? while(*end != '\0') { //end指向字符串的末尾
? ? ? ? end++;
? ? }
? ? --end;
? ? char temp;
? ? while(begin < end) { //交換兩個(gè)字符
? ? ? ? temp = *begin;
? ? ? ? *begin = *end;
? ? ? ? *end = temp;
? ? ? ? begin++;
? ? ? ? end--;
? ? }
? ? return str; //返回結(jié)果
}
67.寫一個(gè)函數(shù),將字符串翻轉(zhuǎn)标捺,翻轉(zhuǎn)方式如下:“I am a student”反轉(zhuǎn)成“student a am I”懊纳,不借助任何庫(kù)函數(shù)
? 1 #include "stdio.h"
? 2 #include <iostream>
? 3 using namespace std;
? 4
? 5 void revesal(char * start, char* end){
? 6? ? char *temp_s = start;
? 7? ? char *temp_e = end;
? 8? ? while(temp_s < temp_e){
? 9? ? ? ? char temp= *temp_s;
10? ? ? ? *temp_s= *temp_e;
11? ? ? ? *temp_e = temp;
12? ? ? ? ++temp_s;
13? ? ? ? --temp_e;
14? ? }
15? ? return;
16 }
17
18 void revesal_str(char *str){
19? ? if(str == NULL){
20? ? ? ? return;
21? ? }
22
23? ? char *start = str;
24? ? char *end = str;
25
26? ? while(*++end !='\0');
27? ? revesal(start, end-1);
28? ? cout << str << endl;
29? ? char *sub_start = str;
30? ? while(start < end + 1 ){
31? ? ? ? if(*start == ' ' || *start == '\0'){
32? ? ? ? ? ? char *temp = start - 1;
33? ? ? ? ? ? revesal(sub_start,temp);
34? ? ? ? ? ? while(*++start ==' ');
35? ? ? ? ? ? sub_start = start;
36? ? ? ? ? ? continue;
37? ? ? ? }
38? ? ? ? ++start;
39? ? }
40 }
68.析構(gòu)函數(shù)可以拋出異常嗎揉抵?為什么不能拋出異常?除了資源泄露嗤疯,還有其他需考慮的因素嗎冤今?
C++標(biāo)準(zhǔn)指明析構(gòu)函數(shù)不能、也不應(yīng)該拋出異常茂缚。C++異常處理模型最大的特點(diǎn)和優(yōu)勢(shì)就是對(duì)C++中的面向?qū)ο筇峁┝俗顝?qiáng)大的無(wú)縫支持戏罢。那么如果對(duì)象在運(yùn)行期間出現(xiàn)了異常,C++異常處理模型有責(zé)任清除那些由于出現(xiàn)異常所導(dǎo)致的已經(jīng)失效了的對(duì)象(也即對(duì)象超出了它原來(lái)的作用域)脚囊,并釋放對(duì)象原來(lái)所分配的資源龟糕, 這就是調(diào)用這些對(duì)象的析構(gòu)函數(shù)來(lái)完成釋放資源的任務(wù),所以從這個(gè)意義上說(shuō)悔耘,析構(gòu)函數(shù)已經(jīng)變成了異常處理的一部分讲岁。
1)如果析構(gòu)函數(shù)拋出異常,則異常點(diǎn)之后的程序不會(huì)執(zhí)行衬以,如果析構(gòu)函數(shù)在異常點(diǎn)之后執(zhí)行了某些必要的動(dòng)作比如釋放某些資源催首,則這些動(dòng)作不會(huì)執(zhí)行,會(huì)造成諸如資源泄漏的問(wèn)題泄鹏。
2)通常異常發(fā)生時(shí),c++的機(jī)制會(huì)調(diào)用已經(jīng)構(gòu)造對(duì)象的析構(gòu)函數(shù)來(lái)釋放資源秧耗,此時(shí)若析構(gòu)函數(shù)本身也拋出異常备籽,則前一個(gè)異常尚未處理,又有新的異常分井,會(huì)造成程序崩潰的問(wèn)題车猬。
69. 拷貝構(gòu)造函數(shù)作用及用途?什么時(shí)候需要自定義拷貝構(gòu)造函數(shù)尺锚?
一般如果構(gòu)造函數(shù)中存在動(dòng)態(tài)內(nèi)存分配珠闰,則必須定義拷貝構(gòu)造函數(shù)。否則瘫辩,可能會(huì)導(dǎo)致兩個(gè)對(duì)象成員指向同一地址伏嗜,出現(xiàn)“指針懸掛問(wèn)題”。
70. 100萬(wàn)個(gè)32位整數(shù)伐厌,如何最快找到中位數(shù)承绸。能保證每個(gè)數(shù)是唯一的,如何實(shí)現(xiàn)O(N)算法挣轨?
1).內(nèi)存足夠時(shí):快排
2).內(nèi)存不足時(shí):分桶法:化大為小军熏,把所有數(shù)劃分到各個(gè)小區(qū)間,把每個(gè)數(shù)映射到對(duì)應(yīng)的區(qū)間里卷扮,對(duì)每個(gè)區(qū)間中數(shù)的個(gè)數(shù)進(jìn)行計(jì)數(shù)荡澎,數(shù)一遍各個(gè)區(qū)間均践,看看中位數(shù)落在哪個(gè)區(qū)間,若夠小摩幔,使用基于內(nèi)存的算法彤委,否則 繼續(xù)劃分
71. OFFSETOF(s, m)的宏定義,s是結(jié)構(gòu)類型热鞍,m是s的成員葫慎,求m在s中的偏移量。
#define OFFSETOF(s, m) size_t(&((s*)0)->m)
72. C++虛函數(shù)是如何實(shí)現(xiàn)的薇宠?
使用虛函數(shù)表偷办。 C++對(duì)象使用虛表, 如果是基類的實(shí)例澄港,對(duì)應(yīng)位置存放的是基類的函數(shù)指針椒涯;如果是繼承類,對(duì)應(yīng)位置存放的是繼承類的函數(shù)指針(如果在繼承類有實(shí)現(xiàn))回梧。所以 废岂,當(dāng)使用基類指針調(diào)用對(duì)象方法時(shí),也會(huì)根據(jù)具體的實(shí)例狱意,調(diào)用到繼承類的方法湖苞。
73. C++的虛函數(shù)有什么作用?
虛函數(shù)作用是實(shí)現(xiàn)多態(tài)详囤,虛函數(shù)其實(shí)是實(shí)現(xiàn)封裝财骨,使得使用者不需要關(guān)心實(shí)現(xiàn)的細(xì)節(jié)。在很多設(shè)計(jì)模式中都是這樣用法藏姐,例如Factory隆箩、Bridge、Strategy模式羔杨。
74.MFC中CString是類型安全類嗎捌臊,為什么?
不是兜材,其他數(shù)據(jù)類型轉(zhuǎn)換到CString可以使用CString的成員函數(shù)Format來(lái)轉(zhuǎn)換
74.動(dòng)態(tài)鏈接庫(kù)的兩種使用方法及特點(diǎn)理澎?
1).載入時(shí)動(dòng)態(tài)鏈接,模塊非常明確調(diào)用某個(gè)導(dǎo)出函數(shù)护姆,使得他們就像本地函數(shù)一樣矾端。這需要鏈接時(shí)鏈接那些函數(shù)所在DLL的導(dǎo)入庫(kù),導(dǎo)入庫(kù)向系統(tǒng)提供了載入DLL時(shí)所需的信息及DLL函數(shù)定位卵皂。
2)運(yùn)行時(shí)動(dòng)態(tài)鏈接秩铆。