1.在C++ 程序中調(diào)用被C 編譯器編譯后的函數(shù)纸巷,為什么要加extern “C”?
答:首先眶痰,extern是C/C++語(yǔ)言中表明函數(shù)和全局變量作用范圍的關(guān)鍵字瘤旨,該關(guān)鍵字告訴編譯器,其聲明的函數(shù)和變量可以在本模塊或其它模塊中使用竖伯。
通常存哲,在模塊的頭文件中對(duì)本模塊提供給其它模塊引用的函數(shù)和全局變量以關(guān)鍵字extern聲明。extern "C"是連接申明(linkage
declaration),被extern
"C"修飾的變量和函數(shù)是按照C語(yǔ)言方式編譯和連接的七婴。作為一種面向?qū)ο蟮恼Z(yǔ)言祟偷,C++支持函數(shù)重載,而過(guò)程式語(yǔ)言C則不支持打厘。函數(shù)被C++編譯后在符號(hào)庫(kù)中的名字與C語(yǔ)言的不同修肠。例如,假設(shè)某個(gè)函數(shù)的原型為:void
foo( int x, int y
);該函數(shù)被C編譯器編譯后在符號(hào)庫(kù)中的名字為_(kāi)foo婚惫,而C++編譯器則會(huì)產(chǎn)生像_foo_int_int之類的名字氛赐。這樣的名字包含了函數(shù)名魂爪、函數(shù)參數(shù)數(shù)量及類型信息,C++就是靠這種機(jī)制來(lái)實(shí)現(xiàn)函數(shù)重載的艰管。
所以滓侍,可以用一句話概括extern “C”這個(gè)聲明的真實(shí)目的:解決名字匹配問(wèn)題,實(shí)現(xiàn)C++與C的混合編程牲芋。
2.頭文件中的ifndef/define/endif有什么作用撩笆?
答:這是C++預(yù)編譯頭文件保護(hù)符,保證即使文件被多次包含缸浦,頭文件也只定義一次夕冲。
3. #include<file.h> 與 #include "file.h"的區(qū)別?
答:前者是從標(biāo)準(zhǔn)庫(kù)路徑尋找和引用file.h裂逐,而后者是從當(dāng)前工作路徑搜尋并引用file.h歹鱼。
4.評(píng)價(jià)一下C/C++各自的特點(diǎn)
答:C語(yǔ)言是一種結(jié)構(gòu)化語(yǔ)言,面向過(guò)程卜高,基于算法和數(shù)據(jù)結(jié)構(gòu)弥姻,所考慮的是如何通過(guò)一個(gè)過(guò)程或者函數(shù)從輸入得到輸出;
C++是面向?qū)ο蟛籼危陬愅ザ亍?duì)象和繼承,所考慮的是如何構(gòu)造一個(gè)對(duì)象模型薪缆,讓這個(gè)模型能夠契合與之對(duì)應(yīng)的問(wèn)題秧廉,通過(guò)獲取對(duì)象的狀態(tài)信息得到輸出或?qū)崿F(xiàn)過(guò)程控制。
5.const 有什么用途拣帽?
答:在C/C++中疼电,(1)可以定義const常量,(2)修飾函數(shù)的返回值和形參诞外;
在C++中澜沟,還可以修飾函數(shù)的定義體,定義類的const成員函數(shù)峡谊。被const修飾的東西受到強(qiáng)制保護(hù)茫虽,可以預(yù)防意外的變動(dòng),提高了程序的健壯性既们。
6.const和#define有什么區(qū)別濒析?
答:(1)const和#define都可以定義常量,但是const用途更廣啥纸。
(2)const 常量有數(shù)據(jù)類型号杏,而宏常量沒(méi)有數(shù)據(jù)類型。編譯器可以對(duì)前者進(jìn)行類型安全檢查。而對(duì)后者只進(jìn)行字符替換盾致,沒(méi)有類型安全檢查主经,并且在字符替換可能會(huì)產(chǎn)生意料不到的錯(cuò)誤。
(3) 有些集成化的調(diào)試工具可以對(duì)const 常量進(jìn)行調(diào)試庭惜,但是不能對(duì)宏常量進(jìn)行調(diào)試罩驻。
7.關(guān)于sizeof小結(jié)的。
答:sizeof計(jì)算的是在棧中分配的內(nèi)存大小护赊。
(1) sizeof不計(jì)算static變量占得內(nèi)存惠遏;
(2) 32位系統(tǒng)的指針的大小是4個(gè)字節(jié),64位系統(tǒng)的指針是8字節(jié)骏啰,而不用管指針類型节吮;
(3) char型占1個(gè)字節(jié),int占4個(gè)字節(jié)判耕,short int占2個(gè)字節(jié)
long int占4個(gè)字節(jié)透绩,float占4字節(jié),double占8字節(jié)壁熄,string占4字節(jié)
一個(gè)空類占1個(gè)字節(jié)渺贤,單一繼承的空類占1個(gè)字節(jié),虛繼承涉及到虛指針?biāo)哉?個(gè)字節(jié)
(4) 數(shù)組的長(zhǎng)度:
若指定了數(shù)組長(zhǎng)度请毛,則不看元素個(gè)數(shù),總字節(jié)數(shù)=數(shù)組長(zhǎng)度*sizeof(元素類型)
若沒(méi)有指定長(zhǎng)度瞭亮,則按實(shí)際元素個(gè)數(shù)類確定
Ps:若是字符數(shù)組方仿,則應(yīng)考慮末尾的空字符。
(5) 結(jié)構(gòu)體對(duì)象的長(zhǎng)度
在默認(rèn)情況下统翩,為方便對(duì)結(jié)構(gòu)體內(nèi)元素的訪問(wèn)和管理仙蚜,當(dāng)結(jié)構(gòu)體內(nèi)元素長(zhǎng)度小于處理器位數(shù)的時(shí)候,便以結(jié)構(gòu)體內(nèi)最長(zhǎng)的數(shù)據(jù)元素的長(zhǎng)度為對(duì)齊單位厂汗,即為其整數(shù)倍委粉。若結(jié)構(gòu)體內(nèi)元素長(zhǎng)度大于處理器位數(shù)則以處理器位數(shù)為單位對(duì)齊。
(6) unsigned影響的只是最高位的意義娶桦,數(shù)據(jù)長(zhǎng)度不會(huì)改變贾节,所以sizeof(unsigned int)=4
(7) 自定義類型的sizeof取值等于它的類型原型取sizeof
(8) 對(duì)函數(shù)使用sizeof,在編譯階段會(huì)被函數(shù)的返回值的類型代替
(9) sizeof后如果是類型名則必須加括號(hào)衷畦,如果是變量名可以不加括號(hào)栗涂,這是因?yàn)閟izeof是運(yùn)算符
(10) 當(dāng)使用結(jié)構(gòu)類型或者變量時(shí),sizeof返回實(shí)際的大小祈争。當(dāng)使用靜態(tài)數(shù)組時(shí)返回?cái)?shù)組的全部大小斤程,sizeof不能返回動(dòng)態(tài)數(shù)組或者外部數(shù)組的尺寸
8.sizeof與strlen的區(qū)別?
答: (1)sizeof的返回值類型為size_t(unsigned int)菩混;
(2)sizeof是運(yùn)算符忿墅,而strlen是函數(shù)扁藕;
(3)sizeof可以用類型做參數(shù),其參數(shù)可以是任意類型的或者是變量疚脐、函數(shù)亿柑,而strlen只能用char*做參數(shù),且必須是以’\0’結(jié)尾亮曹;
(4)數(shù)組作sizeof的參數(shù)時(shí)不會(huì)退化為指針橄杨,而傳遞給strlen是就退化為指針;
(5)sizeo是編譯時(shí)的常量照卦,而strlen要到運(yùn)行時(shí)才會(huì)計(jì)算出來(lái)式矫,且是字符串中字符的個(gè)數(shù)而不是內(nèi)存大小役耕;
9.指針和引用的區(qū)別采转?
答:指針和引用都提供了間接操作對(duì)象的功能。
(1) 指針定義時(shí)可以不初始化瞬痘,而引用在定義時(shí)就要初始化故慈,和一個(gè)對(duì)象綁定,而且一經(jīng)綁定框全,只要引用存在察绷,就會(huì)一直保持和該對(duì)象的綁定;
(2) 賦值行為的差異:指針賦值是將指針重新指向另外一個(gè)對(duì)象津辩,而引用賦值則是修改對(duì)象本身拆撼;
(3) 指針之間存在類型轉(zhuǎn)換,而引用分const引用和非const應(yīng)用喘沿,非const引用只能和同類型的對(duì)象綁定闸度,const引用可以綁定到不同但相關(guān)類型的對(duì)象或者右值
10.?dāng)?shù)組和指針的區(qū)別?
答:(1)數(shù)組要么在全局?jǐn)?shù)據(jù)區(qū)被創(chuàng)建蚜印,要么在棧上被創(chuàng)建莺禁;指針可以隨時(shí)指向任意類型的內(nèi)存塊;
(2)修改內(nèi)容上的差別:
char a[] = “hello”;
a[0] = ‘X’;
char *p = “world”; // 注意p 指向常量字符串
p[0] = ‘X’; // 編譯器不能發(fā)現(xiàn)該錯(cuò)誤窄赋,運(yùn)行時(shí)錯(cuò)誤
(3)用運(yùn)算符sizeof 可以計(jì)算出數(shù)組的容量(字節(jié)數(shù))哟冬。sizeof(p),p 為指針得到的是一個(gè)指針變量的字節(jié)數(shù),而不是p
所指的內(nèi)存容量忆绰。C++/C
語(yǔ)言沒(méi)有辦法知道指針?biāo)傅膬?nèi)存容量柒傻,除非在申請(qǐng)內(nèi)存時(shí)記住它。注意當(dāng)數(shù)組作為函數(shù)的參數(shù)進(jìn)行傳遞時(shí)较木,該數(shù)組自動(dòng)退化為同類型的指針红符。
11.空指針和懸垂指針的區(qū)別?
答:空指針是指被賦值為NULL的指針;delete指向動(dòng)態(tài)分配對(duì)象的指針將會(huì)產(chǎn)生懸垂指針预侯。
(1) 空指針可以被多次delete致开,而懸垂指針再次刪除時(shí)程序會(huì)變得非常不穩(wěn)定;
(2) 使用空指針和懸垂指針都是非法的萎馅,而且有可能造成程序崩潰双戳,如果指針是空指針,盡管同樣是崩潰糜芳,但和懸垂指針相比是一種可預(yù)料的崩潰飒货。
12.C++中有malloc/free,為什么還有new/delete峭竣?
答:malloc/free是C/C++標(biāo)準(zhǔn)庫(kù)函數(shù)塘辅,new/delete是C++運(yùn)算符。他們都可以用于動(dòng)態(tài)申請(qǐng)和釋放內(nèi)存皆撩。
對(duì)于內(nèi)置類型數(shù)據(jù)而言扣墩,二者沒(méi)有多大區(qū)別。malloc申請(qǐng)內(nèi)存的時(shí)候要制定分配內(nèi)存的字節(jié)數(shù)扛吞,而且不會(huì)做初始化呻惕;new申請(qǐng)的時(shí)候有默認(rèn)的初始化,同時(shí)可以指定初始化滥比;
對(duì)于類類型的對(duì)象而言亚脆,用malloc/free無(wú)法滿足要求的。對(duì)象在創(chuàng)建的時(shí)候要自動(dòng)執(zhí)行構(gòu)造函數(shù)盲泛,消亡之前要調(diào)用析構(gòu)函數(shù)型酥。由于malloc/free是庫(kù)函數(shù)而不是運(yùn)算符,不在編譯器控制之內(nèi)查乒,不能把執(zhí)行構(gòu)造函數(shù)和析構(gòu)函數(shù)的任務(wù)強(qiáng)加給它,因此郁竟,C++還需要new/delete玛迄。
13.什么是智能指針?
答:當(dāng)類中有指針成員時(shí)棚亩,一般有兩種方式來(lái)管理指針成員:一是采用值型的方式管理蓖议,每個(gè)類對(duì)象都保留一份指針指向的對(duì)象的拷貝;另一種更優(yōu)雅的方式是使用智能指針讥蟆,從而實(shí)現(xiàn)指針指向的對(duì)象的共享勒虾。
智能指針的一種通用實(shí)現(xiàn)技術(shù)是使用引用計(jì)數(shù)。智能指針類將一個(gè)計(jì)數(shù)器與類指向的對(duì)象相關(guān)聯(lián)瘸彤,引用計(jì)數(shù)跟蹤該類有多少個(gè)對(duì)象共享同一指針修然。
每次創(chuàng)建類的新對(duì)象時(shí),初始化指針并將引用計(jì)數(shù)置為1;當(dāng)對(duì)象作為另一對(duì)象的副本而創(chuàng)建時(shí)愕宋,拷貝構(gòu)造函數(shù)拷貝指針并增加與之相應(yīng)的引用計(jì)數(shù)玻靡;對(duì)一個(gè)對(duì)象進(jìn)行賦值時(shí),賦值操作符減少左操作數(shù)所指對(duì)象的引用計(jì)數(shù)(如果引用計(jì)數(shù)為減至0中贝,則刪除對(duì)象)囤捻,并增加右操作數(shù)所指對(duì)象的引用計(jì)數(shù);調(diào)用析構(gòu)函數(shù)時(shí)邻寿,構(gòu)造函數(shù)減少引用計(jì)數(shù)(如果引用計(jì)數(shù)減至0征绸,則刪除基礎(chǔ)對(duì)象)贿堰。
14.面向?qū)ο蠹夹g(shù)的基本概念是什么,三個(gè)基本特征是什么?
答:基本概念:類佳头、對(duì)象、繼承零蓉; 基本特征:封裝卿嘲、繼承、多態(tài)淀弹。
封裝:將低層次的元素組合起來(lái)形成新的丹壕、更高實(shí)體的技術(shù);
繼承:廣義的繼承有三種實(shí)現(xiàn)形式:實(shí)現(xiàn)繼承薇溃、可視繼承菌赖、接口繼承。
多態(tài):允許將子類類型的指針賦值給父類類型的指針
15.C++空類默認(rèn)有哪些成員函數(shù)沐序?
答:默認(rèn)構(gòu)造函數(shù)琉用、析構(gòu)函數(shù)、復(fù)制構(gòu)造函數(shù)策幼、賦值函數(shù)
16.哪一種成員變量可以在一個(gè)類的實(shí)例之間共享邑时?
答:static靜態(tài)成員變量
17.繼承層次中,為什么基類析構(gòu)函數(shù)是虛函數(shù)特姐?
答:編譯器總是根據(jù)類型來(lái)調(diào)用類成員函數(shù)晶丘。但是一個(gè)派生類的指針可以安全地轉(zhuǎn)化為一個(gè)基類的指針。這樣刪除一個(gè)基類的指針的時(shí)候唐含,C++不管這個(gè)指針指向一個(gè)基類對(duì)象還是一個(gè)派生類的對(duì)象浅浮,調(diào)用的都是基類的析構(gòu)函數(shù)而不是派生類的。如果你依賴于派生類的析構(gòu)函數(shù)的代碼來(lái)釋放資源捷枯,而沒(méi)有重載析構(gòu)函數(shù)滚秩,那么會(huì)有資源泄漏。
18.為什么構(gòu)造函數(shù)不能為虛函數(shù)淮捆?
答:虛函數(shù)采用一種虛調(diào)用的方法郁油。需調(diào)用是一種可以在只有部分信息的情況下工作的機(jī)制本股。如果創(chuàng)建一個(gè)對(duì)象,則需要知道對(duì)象的準(zhǔn)確類型已艰,因此構(gòu)造函數(shù)不能為虛函數(shù)痊末。
19.如果虛函數(shù)是有效的,那為什么不把所有函數(shù)設(shè)為虛函數(shù)哩掺?
答:不行凿叠。首先,虛函數(shù)是有代價(jià)的嚼吞,由于每個(gè)虛函數(shù)的對(duì)象都要維護(hù)一個(gè)虛函數(shù)表盒件,因此在使用虛函數(shù)的時(shí)候都會(huì)產(chǎn)生一定的系統(tǒng)開(kāi)銷,這是沒(méi)有必要的舱禽。
20.構(gòu)造函數(shù)可以是內(nèi)聯(lián)函數(shù)
21.什么是多態(tài)炒刁?多態(tài)有什么作用?
答:多態(tài)就是將基類類型的指針或者引用指向派生類型的對(duì)象誊稚。多態(tài)通過(guò)虛函數(shù)機(jī)制實(shí)現(xiàn)翔始。
多態(tài)的作用是接口重用。
22.重載和覆蓋有什么區(qū)別里伯?
答:虛函數(shù)是基類希望派生類重新定義的函數(shù)城瞎,派生類重新定義基類虛函數(shù)的做法叫做覆蓋;
重載就在允許在相同作用域中存在多個(gè)同名的函數(shù)疾瓮,這些函數(shù)的參數(shù)表不同脖镀。重載的概念不屬于面向?qū)ο缶幊蹋幾g器根據(jù)函數(shù)不同的形參表對(duì)同名函數(shù)的名稱做修飾狼电,然后這些同名函數(shù)就成了不同的函數(shù)蜒灰。
重載的確定是在編譯時(shí)確定,是靜態(tài)的肩碟;虛函數(shù)則是在運(yùn)行時(shí)動(dòng)態(tài)確定强窖。
23.公有繼承、受保護(hù)繼承削祈、私有繼承
答:(1)公有繼承時(shí)翅溺,派生類對(duì)象可以訪問(wèn)基類中的公有成員,派生類的成員函數(shù)可以訪問(wèn)基類中的公有和受保護(hù)成員岩瘦;
(2)私有繼承時(shí),基類的成員只能被直接派生類的成員訪問(wèn)窿撬,無(wú)法再往下繼承启昧;
(3)受保護(hù)繼承時(shí),基類的成員也只被直接派生類的成員訪問(wèn)劈伴,無(wú)法再往下繼承密末。
24.公有繼承時(shí)基類受保護(hù)的成員握爷,可以通過(guò)派生類對(duì)象訪問(wèn)但不能修改。
25.有哪幾種情況只能用構(gòu)造函數(shù)初始化列表而不能用賦值初始化严里?
答:const成員新啼,引用成員
26.什么是虛指針?
答:虛指針或虛函數(shù)指針是虛函數(shù)的實(shí)現(xiàn)細(xì)節(jié)刹碾。帶有虛函數(shù)的每一個(gè)對(duì)象都有一個(gè)虛指針指向該類的虛函數(shù)表燥撞。
27.C++如何阻止一個(gè)類被實(shí)例化?一般在什么時(shí)候?qū)?gòu)造函數(shù)聲明為private迷帜?
答:(1)將類定義為抽象基類或者將構(gòu)造函數(shù)聲明為private物舒;
(2)不允許類外部創(chuàng)建類對(duì)象,只能在類內(nèi)部創(chuàng)建對(duì)象
28.main函數(shù)執(zhí)行之前會(huì)執(zhí)行什么戏锹?執(zhí)行之后還能執(zhí)行代碼嗎冠胯?
答:(1)全局對(duì)象的構(gòu)造函數(shù)會(huì)在main函數(shù)之前執(zhí)行;
(2)可以锦针,可以用_onexit 注冊(cè)一個(gè)函數(shù)荠察,它會(huì)在main 之后執(zhí)行;
如果你需要加入一段在main退出后執(zhí)行的代碼,可以使用atexit()函數(shù)奈搜,注冊(cè)一個(gè)函數(shù)悉盆。
語(yǔ)法:
#include <stdlib.h>
#include <stdio.h>
int atexit(void (*function")(void));
void fn1( void ), fn2( void ), fn3( void );
int main( void )
{
atexit(fn1);
atexit( fn2 );
printf( "This is executed first.\n" );
}
void fn1()
{
printf( " This is\n" );
}
void fn2()
{
printf( " executed next." );
}
結(jié)果:
This is executed first.
This is executed next.
29.請(qǐng)描述進(jìn)程和線程的區(qū)別?
答:(1)進(jìn)程是程序的一次執(zhí)行媚污,線程是進(jìn)程中的執(zhí)行單元舀瓢;
(2)進(jìn)程間是獨(dú)立的,這表現(xiàn)在內(nèi)存空間耗美、上下文環(huán)境上京髓,線程運(yùn)行在進(jìn)程中;
(3)一般來(lái)講商架,進(jìn)程無(wú)法突破進(jìn)程邊界存取其他進(jìn)程內(nèi)的存儲(chǔ)空間堰怨;而同一進(jìn)程所產(chǎn)生的線程共享內(nèi)存空間;
(4)同一進(jìn)程中的兩段代碼不能同時(shí)執(zhí)行蛇摸,除非引入多線程备图。
30.進(jìn)程間如何通信?
答:信號(hào)赶袄、信號(hào)量揽涮、消息隊(duì)列、共享內(nèi)存
31.在網(wǎng)絡(luò)編程中涉及并發(fā)服務(wù)器饿肺,使用多進(jìn)程與多線程的區(qū)別蒋困?
答:(1)線程執(zhí)行開(kāi)銷小,但不利于資源管理和保護(hù)敬辣;進(jìn)程則相反雪标,進(jìn)程可跨越機(jī)器遷移零院。
(2)多進(jìn)程時(shí)每個(gè)進(jìn)程都有自己的內(nèi)存空間,而多線程間共享內(nèi)存空間村刨;
(3)線程產(chǎn)生的速度快告抄,線程間通信快、切換快嵌牺;
(4)線程的資源利用率比較好打洼;
(5)線程使用公共變量或者資源時(shí)需要同步機(jī)制。
32.說(shuō)一下TCP 3次握手髓梅、4次揮手的全過(guò)程拟蜻。
33.TCP和UDP有什么區(qū)別。
答:
TCP——傳輸控制協(xié)議,提供的是面向連接枯饿、可靠的字節(jié)流服務(wù)酝锅。
當(dāng)客戶和服務(wù)器彼此交換數(shù)據(jù)前,必須先在雙方之間建立一個(gè)TCP連接奢方,之后才能傳輸數(shù)據(jù)搔扁。TCP提供超時(shí)重發(fā),丟棄重復(fù)數(shù)據(jù)蟋字,檢驗(yàn)數(shù)據(jù)稿蹲,流量控制等功能,保證數(shù)據(jù)能從一端傳到另一端鹊奖。
UDP——用戶數(shù)據(jù)報(bào)協(xié)議苛聘,是一個(gè)簡(jiǎn)單的面向數(shù)據(jù)報(bào)的傳輸層協(xié)議。UDP不提供可靠性忠聚,它只是把應(yīng)用程序傳給IP層的數(shù)據(jù)報(bào)發(fā)送出去设哗,但是并不能保證它們能到達(dá)目的地。由于UDP在傳輸數(shù)據(jù)報(bào)前不用在客戶和服務(wù)器之間建立一個(gè)連接两蟀,且沒(méi)有超時(shí)重發(fā)等機(jī)制网梢,故而傳輸速度很快.
TCP協(xié)議和UDP協(xié)議的一些特性區(qū)別如下:
1.TCP協(xié)議在傳送數(shù)據(jù)段的時(shí)候要給段標(biāo)號(hào);UDP 協(xié)議不需要赂毯。
2.TCP協(xié)議可靠战虏;UDP協(xié)議不可靠。
3.TCP協(xié)議是面向連接党涕;UDP協(xié)議采用無(wú)連接烦感。
4.TCP協(xié)議負(fù)載較高,采用虛電路;UDP協(xié)議低負(fù)載膛堤。
5.TCP協(xié)議的發(fā)送方要確認(rèn)接受方是否收到數(shù)據(jù)段(3次握手協(xié)議)手趣。
6.TCP協(xié)議采用窗口技術(shù)和流控制。