一.const用途:
1谍珊、const是用來聲明一個(gè)常量的诅蝶,只讀變量:當(dāng)const修飾指針時(shí)候生,如果const位于星號(hào)的左側(cè)纱皆,則const就是用來修飾指針?biāo)赶虻淖兞客逯海荒?a=3操作,如果const位于星號(hào)的右側(cè)派草,const就是修飾指針本身搀缠,即指針本身是常量,而指針?biāo)赶虻膬?nèi)容不是常量近迁,不能a++操作胡嘿,const int* const a=&b;指針本身和指向的內(nèi)容均為常量。
2钳踊、const修飾函數(shù)的輸入?yún)?shù):對(duì)于非內(nèi)部數(shù)據(jù)類型的輸入?yún)?shù),將“值傳遞”的方式改為“const引用勿侯,目的提高效率”拓瞪,如將void Func(A a)改為voidFun(const A&a),對(duì)于內(nèi)部數(shù)據(jù)類型的輸入?yún)?shù)助琐,不要將“值傳遞”的方式改為“const引用傳遞”祭埂。否則既達(dá)不到高效率的目的,有降低了函數(shù)的可理解性。
3蛆橡、const修飾函數(shù)的返回值:如果給以“指針傳遞”方式的函數(shù)返回值加const修飾舌界,那么函數(shù)返回值(即指針)的內(nèi)容不能被修改,該返回值只能被賦給加const修飾的同類型指針泰演,如const char*GetString(void)呻拌,char*str=GetString()錯(cuò)誤,const char*str=GetString()正確睦焕;如果函數(shù)返回值采用“值傳遞方式”藐握,由于函數(shù)會(huì)把返回值復(fù)制到外部臨時(shí)的存儲(chǔ)單元中,加const修飾沒有任何價(jià)值垃喊,函數(shù)返回值采用“引用傳遞”的場(chǎng)合并不多猾普,這種方式一般只出現(xiàn)在類的賦值函數(shù)中,目的是為了實(shí)現(xiàn)鏈?zhǔn)奖磉_(dá)本谜。
4初家、const修飾成員函數(shù):修飾類的成員函數(shù),char get() const;在后面加const乌助,被const修飾的成員函數(shù)代表不修改成員變量的值溜在,會(huì)提高程序的健壯性。
5眷茁、const常量與#define宏定義的區(qū)別:1炕泳、define宏是在預(yù)處理階段展開,const常量是編譯運(yùn)行階段使用上祈;2培遵、const 常量有數(shù)據(jù)類型,而宏常量沒有數(shù)據(jù)類型登刺;3籽腕、編譯器可以對(duì)前者進(jìn)行類型安全檢查。而對(duì)后者只進(jìn)行字符替換纸俭;4皇耗、define宏僅僅是展開,有多少地方使用揍很,就展開多少次郎楼,不會(huì)分配內(nèi)存,const常量會(huì)在內(nèi)存中分配(可以是堆中也可以是棧中)窒悔。
二.static用途:
1呜袁、作用域隱藏。當(dāng)一個(gè)工程有多個(gè)文件的時(shí)候简珠,用static修飾的函數(shù)或變量只能夠在本文件中可見阶界,文件外不可見;
2、全局生命周期膘融。用static修飾的變量或函數(shù)生命周期是全局的芙粱。被static修飾的變量存儲(chǔ)在靜態(tài)數(shù)據(jù)區(qū);
3氧映、函數(shù)體內(nèi)static變量的作用范圍為該函數(shù)體春畔,不同于auto變量,該變量的內(nèi)存只被分配一次屯耸,因此其值在下次調(diào)用時(shí)仍維持上次的值拐迁;
4、static修飾的變量默認(rèn)初始化為0疗绣;
5线召、在類中的static成員變量屬于整個(gè)類所擁有,對(duì)類的所有對(duì)象只有一份拷貝多矮;
6缓淹、在類中的static成員函數(shù)屬于整個(gè)類所擁有,這個(gè)函數(shù)不接收this指針塔逃,因而只能訪問類的static成員變量讯壶。
三.sizeof()
1、sizeof是運(yùn)算符湾盗,并不是函數(shù)伏蚊;
2、sizeof不能求得void類型的長度格粪;
3躏吊、sizeof的用法是sizeof(參數(shù)),這個(gè)參數(shù)可以是數(shù)組帐萎,指針比伏,類型,對(duì)象疆导,甚至是函數(shù)赁项,其值在編譯的時(shí)候就計(jì)算好了,
4澈段、sizeof可以對(duì)函數(shù)調(diào)用求大小悠菜,并且求得的大小等于函數(shù)返回類型的大小,但是不執(zhí)行函數(shù)體败富。
5悔醋、sizeof指針變量與指針?biāo)笇?duì)象無關(guān),32位是4,64位是8囤耳;
6、sizeof求得結(jié)構(gòu)體(及其對(duì)象)的大小并不等于各個(gè)數(shù)據(jù)成員對(duì)象的大小之和(內(nèi)存對(duì)齊)
7、一個(gè)空的數(shù)據(jù)類型充择,里面沒有任何成員變量和成員函數(shù)德玫,對(duì)該類型求sizeof,結(jié)果是1椎麦,當(dāng)我們聲明該類型的實(shí)例時(shí)宰僧,它必須在內(nèi)存中占有一定的空間,否則無法使用這些實(shí)例观挎,至于占用多少內(nèi)存琴儿,由編譯器決定,如果在該類型中添加一個(gè)構(gòu)造函數(shù)和析構(gòu)函數(shù)嘁捷,再求sizeof造成,還是1,調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)只需要知道函數(shù)的地址即可雄嚣,而這些地址只與類型相關(guān)晒屎,而與類型的實(shí)例無關(guān),編譯器也不會(huì)因?yàn)檫@兩個(gè)函數(shù)而在實(shí)例內(nèi)添加任何額外的信息缓升,如果把析構(gòu)函數(shù)標(biāo)記為虛函數(shù)鼓鲁,C++的編譯器一旦發(fā)現(xiàn)一個(gè)類型中有虛函數(shù),就會(huì)為該類型生成虛函數(shù)表港谊,并在該類型的每一個(gè)實(shí)例中添加一個(gè)指向虛函數(shù)表的指針骇吭,在32位機(jī)器上,一個(gè)指針占4字節(jié)空間歧寺,因此求sizeof得到4燥狰;如果是64位則為8。
四.sizeof與strlen的區(qū)別
1成福、sizeof是運(yùn)算符碾局,而strlen是函數(shù)strlen(char*);
2奴艾、sizeof的用法是sizeof(參數(shù))净当,這個(gè)參數(shù)可以是數(shù)組,指針蕴潦,類型像啼,對(duì)象,甚至是函數(shù)潭苞,其值在編譯的時(shí)候就計(jì)算好了忽冻,而strlen的參數(shù)必須是字符型指針(char*),其值必須在函數(shù)運(yùn)行的時(shí)候才能計(jì)算出來;
3此疹、strlen(char*)函數(shù)求的是字符串的實(shí)際長度僧诚,它求的方法是從開始遇到第一個(gè)’\0’遮婶,如果你只定義沒有給它賦初值,這個(gè)結(jié)果是不定的湖笨,它從指針指向的首地址一直找下去旗扑,直到遇到’\0’為止。 如char aa[10];strlen(aa);//結(jié)果是不定的? sizeof(aa); //結(jié)果是10
4慈省、當(dāng)數(shù)組作為參數(shù)傳遞給函數(shù)的時(shí)候臀防,傳的是指針,而不是數(shù)組边败,傳遞數(shù)組的首地址袱衷;比如:
char aaa[]={"LRPLRP"};
int a,b;
fun(aaa,a,b);
void fun(char aaa[],int&a,int&b)
{
? a=strlen(aaa);
? b=sizeof(aaa);
}
結(jié)果是:a=6,b=4.在函數(shù)內(nèi)部笑窜,雖然aaa轉(zhuǎn)化成指針致燥,但是strlen還是測(cè)試aaa開始直到’\0’為止的字符串的長度,而sizeof則是測(cè)指針的長度怖侦。
五.內(nèi)存對(duì)齊
1篡悟、原因:現(xiàn)代計(jì)算機(jī)中內(nèi)存空間都是按照byte劃分的,從理論上講似乎對(duì)任何類型的變量的訪問可以從任何地址開始匾寝,但實(shí)際情況是在訪問特定類型變量的時(shí)候經(jīng)常在特定的內(nèi)存地址訪問搬葬,這就需要各種類型數(shù)據(jù)按照一定的規(guī)則在空間上排列,而不是順序的一個(gè)接一個(gè)的排放艳悔,這就是對(duì)齊急凰,若不對(duì)齊,則會(huì)在存取效率讀取效率上下降猜年。
2抡锈、規(guī)則:默認(rèn)對(duì)齊系數(shù)是8,可以通過預(yù)編譯命令#pragma pack(n)乔外,n=1,2,4,8,16來改變這一系數(shù)床三,偏移位為min(結(jié)構(gòu)中最大數(shù)據(jù)成員長度,對(duì)齊系數(shù))的最小整數(shù)倍杨幼。
3撇簿、即使是同樣數(shù)目與數(shù)量的數(shù)據(jù)成員,在擺放的順序不同時(shí)struct的大小也會(huì)不同差购,比如
struct{
? ? char a;
? ? int b;
? ? char d;
? ? short c;
}myStruct;? ? ? sizeof(myStruct)結(jié)果為12四瘫;
struct{
? ? char a;
? ? char d;
? ? short c;
? ? int b;
}myStruct;? ? ? sizeof(myStruct)結(jié)果為8;
4欲逃、存在內(nèi)存對(duì)齊的情況下找蜜,不能使用函數(shù)memcmp來判斷兩個(gè)結(jié)構(gòu)體是否相等:memcmp函數(shù)是逐個(gè)字節(jié)進(jìn)行比較的,而struct存在字節(jié)對(duì)齊稳析,字節(jié)對(duì)齊時(shí)補(bǔ)的字節(jié)內(nèi)容是隨機(jī)的洗做,會(huì)產(chǎn)生垃圾值弓叛,所以無法比較,只能逐個(gè)比較其成員诚纸。
六.memcmp與strncmp區(qū)別
對(duì)于memcmp()邪码,如果兩個(gè)字符串相同而且count大于字符串長度的話,memcmp不會(huì)在\0處停下來咬清,會(huì)繼續(xù)比較\0后面的內(nèi)存單元,直到_res不為零或者達(dá)到count次數(shù)灌侣。
對(duì)于strncmp()蜻展,比較必定會(huì)在最短的字符串的末尾停下來泽腮,即使count還未為零。
所以掘剪,如果想使用memcmp比較字符串,要保證count不能超過最短字符串的長度奈虾,否則結(jié)果有可能是錯(cuò)誤的夺谁。
七.指針和引用區(qū)別
1、引用是變量的一個(gè)別名肉微,內(nèi)部實(shí)現(xiàn)是只讀指針
2匾鸥、引用只能在初始化時(shí)被賦值,其他時(shí)候值不能被改變碉纳,指針的值可以在任何時(shí)候被改變
3勿负、引用不能為NULL,指針可以為NULL
4劳曹、引用變量內(nèi)存單元保存的是被引用變量的地址
5奴愉、“sizeof 引用" = 指向變量的大小 , "sizeof 指針"= 指針本身的大小
6铁孵、指針可以有多級(jí)锭硼,但是引用只能是一級(jí)
八.C++傳值,傳引用蜕劝,傳地址的區(qū)別
1檀头、傳值,是把實(shí)參的值賦值給行參熙宇,那么對(duì)行參的修改鳖擒,不會(huì)影響實(shí)參的值;
2烫止、傳地址蒋荚,是傳值的一種特殊方式,只是他傳遞的是地址馆蠕,不是普通的如int期升,那么傳地址以后惊奇,實(shí)參和行參都指向同一個(gè)對(duì)象;
3播赁、傳引用颂郎,真正的以地址的方式傳遞參數(shù),傳遞以后容为,行參和實(shí)參都是同一個(gè)對(duì)象乓序,只是他們名字不同而已, 對(duì)行參的修改將影響實(shí)參的值坎背;
4替劈、無論你傳值還是傳指針,函數(shù)都會(huì)生成一個(gè)臨時(shí)變量得滤, 但傳引用時(shí)陨献,不會(huì)生成臨時(shí)變量,
5懂更、傳指針時(shí)眨业,在函數(shù)中只能修改指針?biāo)傅膬?nèi)容*p,但不能改變指針本身的指向沮协,即指針地址龄捡,若要修改,則需要使用指針的指針或者指針引用慷暂。
九.malloc和new的區(qū)別
1墅茉、malloc與free是C++/C語言的標(biāo)準(zhǔn)庫函數(shù),new/delete是C++的運(yùn)算符呜呐;
2就斤、申請(qǐng)的內(nèi)存所在位置:new操作符從自由存儲(chǔ)區(qū)上為對(duì)象動(dòng)態(tài)分配內(nèi)存空間,而malloc函數(shù)從堆上動(dòng)態(tài)分配內(nèi)存蘑辑;
3洋机、new內(nèi)存分配失敗時(shí),會(huì)拋出bac_alloc異常洋魂,它不會(huì)返回NULL绷旗;malloc分配內(nèi)存失敗時(shí)返回NULL,需要添加if(a==NULL)進(jìn)行判斷副砍;
4衔肢、是否需要指定內(nèi)存大小:使用new操作符申請(qǐng)內(nèi)存分配時(shí)無須指定內(nèi)存塊的大小豁翎,編譯器會(huì)根據(jù)類型信息自行計(jì)算角骤,而malloc則需要顯式地指出所需內(nèi)存的尺寸;
5心剥、是否調(diào)用構(gòu)造函數(shù)/析構(gòu)函數(shù):new/delete會(huì)調(diào)用對(duì)象的構(gòu)造函數(shù)/析構(gòu)函數(shù)以完成對(duì)象的構(gòu)造/析構(gòu)邦尊。而malloc則不會(huì)背桐;
6、new與malloc是否可以相互調(diào)用:operator new /operator delete的實(shí)現(xiàn)可以基于malloc蝉揍,而malloc的實(shí)現(xiàn)不可以去調(diào)用new链峭;
7、是否可以被重載:opeartor new /operator delete可以被重載又沾,而malloc/free并不允許重載
8弊仪、對(duì)數(shù)組的處理:C++提供了new[]與delete[]來專門處理數(shù)組類型,malloc如果要?jiǎng)討B(tài)分配一個(gè)數(shù)組的內(nèi)存杖刷,還需要我們手動(dòng)自定數(shù)組的大小撼短,如int * ptr=(int *)malloc(sizeof(int)* 10);//分配一個(gè)10個(gè)int元素的數(shù)組。
十.C++內(nèi)存分配
1挺勿、棧區(qū): 由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值喂柒,局部變量的值等不瓶;
2、堆區(qū): 一般由程序員分配釋放灾杰, 若程序員不釋放蚊丐,程序結(jié)束時(shí)可能由OS回收;
3艳吠、自由存儲(chǔ)區(qū):由new分配的內(nèi)存塊麦备,和堆十分相似;
4昭娩、全局/靜態(tài)存儲(chǔ)區(qū):全局變量和靜態(tài)變量被分配到同一塊內(nèi)存中凛篙,程序編譯時(shí)已經(jīng)分配好;
5栏渺、常量存儲(chǔ)區(qū)呛梆,這是一塊比較特殊的存儲(chǔ)區(qū),他們里面存放的是常量磕诊,不允許修改填物;
十一.堆棧區(qū)別:
1、申請(qǐng)方式:棧由系統(tǒng)分配霎终;堆要程序員自己申請(qǐng)并指明大兄突恰;
2莱褒、申請(qǐng)大小限制:棧是一塊連續(xù)的內(nèi)存區(qū)域击困,棧的容量是系統(tǒng)預(yù)先規(guī)定好的,如果申請(qǐng)的空間超過棧的剩余空間广凸,將會(huì)提示overflow沛励,能從棧獲得的空間較性鹩铩;堆是不連續(xù)的內(nèi)存區(qū)域目派,類似與鏈表坤候,因此堆獲得的空間比較靈活,也比較大企蹭;
3白筹、申請(qǐng)效率:棧由系統(tǒng)自動(dòng)分配,速度較快谅摄,但程序員是無法控制的徒河;堆是由new分配的內(nèi)存,一般速度比較慢送漠,而且容易產(chǎn)生內(nèi)存碎片,不過用起來最方便顽照。
十二.線程和進(jìn)程
1、進(jìn)程是表示資源分配的基本單位闽寡,又是調(diào)度運(yùn)行的基本單位代兵;線程是cpu調(diào)度,或者說是程序執(zhí)行的最小單位爷狈;
2植影、線程是進(jìn)程的一部分,所以線程有的時(shí)候被稱為是輕權(quán)進(jìn)程或者輕量級(jí)進(jìn)程涎永;
3思币、系統(tǒng)在運(yùn)行的時(shí)候會(huì)為每個(gè)進(jìn)程分配不同的內(nèi)存區(qū)域,但是不會(huì)為線程分配內(nèi)存(線程所使用的資源是它所屬的進(jìn)程的資源)羡微,線程組只能共享資源谷饿。
4、線程之間的通信比較方便妈倔。同一進(jìn)程下的線程共享數(shù)據(jù)(比如全局變量各墨,靜態(tài)變量),而進(jìn)程之間的通信只能通過進(jìn)程通信的方式進(jìn)行启涯。
5贬堵、優(yōu)缺點(diǎn):線程執(zhí)行開銷小,但不利于資源的管理和保護(hù)结洼;而進(jìn)程正相反黎做。
6、進(jìn)程之間不會(huì)互相影響松忍,一個(gè)線程掛掉將導(dǎo)致整個(gè)進(jìn)程掛掉蒸殿。
進(jìn)程間的通信方式
管道、有名管道、信號(hào)宏所、共享內(nèi)存酥艳、消息隊(duì)列、信號(hào)量爬骤、套接字充石、文件
十三.空懸指針和野指針的區(qū)別
1、空懸指針:它曾經(jīng)指向一個(gè)有效地址霞玄,但是現(xiàn)在不再指向有效地址骤铃,其實(shí)就是原來的那塊地址不能通過這個(gè)指針區(qū)訪問了,通常是因?yàn)橹羔標(biāo)傅膬?nèi)存單位被釋放了并且不再有效了坷剧;
2惰爬、野指針:它沒有被正確的初始化于是指向一個(gè)隨機(jī)的內(nèi)存地址。存在野指針是一個(gè)嚴(yán)重的錯(cuò)誤惫企。
十四.內(nèi)存泄露與內(nèi)存溢出
1撕瞧、內(nèi)存泄露是指程序中一塊不再使用的內(nèi)存沒有被釋放,造成內(nèi)存保持占用狀態(tài)狞尔,使操作系統(tǒng)不能將內(nèi)存分配給其它的程序(進(jìn)程)丛版。內(nèi)存泄露不是一個(gè)立即會(huì)引發(fā)故障的錯(cuò)誤,但是它將消耗系統(tǒng)內(nèi)存沪么;
2、內(nèi)存溢出指你申請(qǐng)了10個(gè)字節(jié)的空間锌半,但是你在這個(gè)空間寫入11或以上字節(jié)的數(shù)據(jù)禽车,就是溢出;
3刊殉、檢測(cè)是否存在內(nèi)存泄漏問題
STEP1殉摔,在程序中包括以下語句:#define _CRTDBG_MAP_ALLOC? #include<stdlib.h>? #include<crtdbg.h>
STEP2, 在添加了上述語句之后记焊,可以通過在程序中包括以下語句_CrtDumpMemoryLeaks();
十五.C++是不是類型安全的逸月?
答:不是,兩個(gè)不同類型的指針之間可以強(qiáng)制轉(zhuǎn)換(用reinterpret cast)遍膜。C#是類型安全的碗硬。
十六. main函數(shù)執(zhí)行以前,還會(huì)執(zhí)行什么代碼瓢颅?
全局對(duì)象的構(gòu)造函數(shù)會(huì)在main 函數(shù)之前執(zhí)行恩尾。
十七.全局變量和局部變量有什么區(qū)別?是怎么實(shí)現(xiàn)的挽懦?操作系統(tǒng)和編譯器是怎么知道的翰意?
1、生命周期不同:全局變量隨主程序創(chuàng)建和創(chuàng)建,隨主程序銷毀而銷毀冀偶;局部變量在局部函數(shù)內(nèi)部醒第,甚至局部循環(huán)體等內(nèi)部存在,退出就不存在进鸠;
2稠曼、使用方式不同:通過聲明后全局變量程序的各個(gè)部分都可以用到;局部變量只能在局部使用堤如;分配在棧區(qū)蒲列。
3、操作系統(tǒng)和編譯器通過內(nèi)存分配的位置來知道的搀罢,全局變量分配在全局?jǐn)?shù)據(jù)段并且在程序開始運(yùn)行的時(shí)候被加載蝗岖。局部變量則分配在堆棧里面 。
十八.C++中宏與內(nèi)聯(lián)函數(shù)
共同點(diǎn):都是通過避免被調(diào)用的開銷來提高執(zhí)行效率榔至,就是都不會(huì)引起函數(shù)的調(diào)用抵赢,都是在調(diào)用函數(shù)的位置將函數(shù)體展開。
區(qū)別:
1唧取、宏是在編譯器預(yù)處理的時(shí)候?qū)⒑瘮?shù)展開的铅鲤;而inline函數(shù)則是在編譯的時(shí)候展開的;?
2枫弟、使用宏很容易產(chǎn)生錯(cuò)誤邢享,為了避免這些,在定義的時(shí)候我們是將里面每個(gè)參數(shù)括起來淡诗,最后還要一起再括起來骇塘,而inline函數(shù)則沒有必要;
3韩容、宏的參數(shù)檢查比較弱款违,一個(gè)函數(shù)可能實(shí)用于int類型,也有可能實(shí)用于float類型群凶;而inline函數(shù)則有較強(qiáng)的類型檢查插爹,實(shí)用于int就只能是int,如float想用的話请梢,就要靠template了赠尾。
十九.簡述extern"C"的作用
extern關(guān)鍵字:表明函數(shù)和全局變量作用范圍(可見性)的關(guān)鍵字,該關(guān)鍵字告訴編譯器毅弧,其聲明的函數(shù)和變量可以在本模塊或其它模塊中使用萍虽。
extern "C"的目的:實(shí)現(xiàn)類C和C++的混合編程。在C++源文件中的語句前面加上extern "C"形真,表明它按照類C的編譯和連接規(guī)約來編譯和連接杉编,而不是C++的編譯的連接規(guī)約超全。這樣在類C的代碼中就可以調(diào)用C++的函數(shù)或者變量等。
二十.c++11新特性之a(chǎn)uto
1邓馒、作用:使用auto關(guān)鍵字來要求編譯器對(duì)變量的類型進(jìn)行自動(dòng)推導(dǎo)嘶朱;
2、用auto聲明的變量必須初始化
3光酣、函數(shù)和模板參數(shù)不能被聲明為auto
4疏遏、定義在堆上的變量,使用了auto的表達(dá)式必須被初始化
5救军、優(yōu)勢(shì):1)擁有初始化表達(dá)式的復(fù)雜類型變量聲明時(shí)簡化代碼财异;2)可以避免類型聲明時(shí)的麻煩而且避免類型聲明時(shí)的錯(cuò)誤;但是auto不能解決所有的精度問題唱遭。