1、以下代碼會(huì)有什么問題?
cout << (true?1:"1") << endl;
答:操作數(shù)的類型不兼容, int 和 const char*
2、以下代碼輸出什么?
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
cout << boolalpha << ( str1==str2 ) << endl; // 輸出false
cout << boolalpha << ( str3==str4 ) << endl; // 輸出false
cout << boolalpha << ( str5==str6 ) << endl; // 輸出true
答案:數(shù)組名代表的是指針地址,而用const修飾只是代表變量內(nèi)容能否被改變而已。所以第一行和第二行都是輸出0。str5和str6是常量指針,指向同一個(gè)內(nèi)存塊。
3、以下代碼可以輸出0嗎?
struct CLS
{
int m_i;
CLS(int i) : m_i(i) {}
CLS()
{
CLS(0);
}
};
CLS obj;
cout << obj.m_i << endl;
答:不能輸出0。默認(rèn)構(gòu)造函數(shù)里面執(zhí)行的帶參數(shù)的構(gòu)造函數(shù)其實(shí)是創(chuàng)建了一個(gè)新的對象,元對象的成員變量的值沒有做修改。代碼做如下修改可以輸出0:
struct CLS
{
int m_i;
CLS(int i) : m_i(i) {}
CLS()
{
*this = CLS(0);
}
};
4、c++中的空類默認(rèn)產(chǎn)生哪些類成員函數(shù)?
答:默認(rèn)產(chǎn)生 構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、析構(gòu)函數(shù)、賦值運(yùn)算符、取址運(yùn)算符、常量取址運(yùn)算符。
class Empty
{
public:
Empty(); // 缺省構(gòu)造函數(shù)
Empty(const Empty&); // 拷貝構(gòu)造函數(shù)
~Empty(); // 析構(gòu)函數(shù)
Empty& perator=(const Empty&); // 賦值運(yùn)算符
Empty* operator&(); // 取值運(yùn)算符
const Empty* operator&() const; // 取值運(yùn)算符
};
5、下面代碼輸出什么?
float a = 1.0f;
cout < < (int)a < < endl; //輸出1
cout < < (int&)a < < endl; //輸出1065353216
cout < < boolalpha < < ( (int)a == (int&)a ) < < endl; // 輸出 false
//因?yàn)閒loat 1 和 int 1 在內(nèi)存中的表示方法不一樣。
float b = 0.0f;
cout < < (int)b < < endl; //輸出0
cout < < (int&)b < < endl; //輸出0
cout < < boolalpha < < ( (int)b == (int&)b ) < < endl; // 輸出true
//float 0 和 int 0 在內(nèi)存中表示的方法是一樣的。
解釋:float b = 0.0f;
(int)b //把數(shù)據(jù)強(qiáng)轉(zhuǎn)為int型,一般只會(huì)丟失小數(shù)部分
(int)&b //把b的地址轉(zhuǎn)為int數(shù)
(int&)b 把b處的內(nèi)存bit按int型數(shù)據(jù)解釋.
6、寫一個(gè)函數(shù)完成內(nèi)存之間的拷貝
void* mymemcpy(void *dest, const void *src, size_t count)
{
char* pdest = static_cast<char*>(dest);
const char* psrc = static_cast<const char*>(src);
if (pdest > psrc && pdest < (char*)psrc + count ) //能考慮到這種情況就行了
{
for (size_t i = count - 1; i != -1; --i)
pdest[i] = psrc[i];
}
else
{
for (size_t i = 0; i < count; ++i)
pdest[i] = psrc[i];
}
return dest;
}
7、main函數(shù)執(zhí)行完畢后是否可能會(huì)再執(zhí)行其他代碼。
答案:使用atexit或者_(dá)onexit注冊函數(shù)。
atexit是標(biāo)準(zhǔn)C中的函數(shù),建議使用這個(gè)。
onexit是非標(biāo)準(zhǔn)的。有些平臺(tái)上不存在這個(gè)函數(shù)。
8、多態(tài)類中的虛函數(shù)表是Compile-Time,還是Run-Time時(shí)建立的?
答:虛擬函數(shù)表是在編譯期就建立了,各個(gè)虛擬函數(shù)這時(shí)被組織成了一個(gè)虛擬函數(shù)的入口地址的數(shù)組.而對象的隱藏成員--虛擬函數(shù)表指針是在運(yùn)行期--也就是構(gòu)造函數(shù)被調(diào)用時(shí)進(jìn)行初始化的,這是實(shí)現(xiàn)多態(tài)的關(guān)鍵.
9、一個(gè)父類寫了一個(gè)virtual 函數(shù),如果子類覆蓋它的函數(shù)不加virtual ,也能實(shí)現(xiàn)多態(tài)?在子類的空間里,有沒有父類的這個(gè)函數(shù),或者父類的私有變量?
答案:只要基類在定義成員函數(shù)時(shí)已經(jīng)聲明了virtual關(guān)鍵字,在派生類實(shí)現(xiàn)的時(shí)候覆蓋該函數(shù)時(shí),virtual關(guān)鍵字可加可不加,virtual修飾符會(huì)被隱形繼承的,不影響多態(tài)的實(shí)現(xiàn)。子類的空間里有父類的所有變量(static除外)
10、用代碼實(shí)現(xiàn)判斷一個(gè)int類型的數(shù)是否是2的冪,不可用用遞歸。
bool IsTwoPower(int s)
{
return (s > 0) && ((s & (s-1))==0);
}
11、在C++ 程序中調(diào)用被C編譯器編譯后的函數(shù),為什么要加extern “C”聲明?
答:C++語言支持函數(shù)重載,C語言不支持函數(shù)重載。函數(shù)被C++編譯后在庫中的名字與C語言的不同。假設(shè)某個(gè)函數(shù)的原型為: void foo(int x, int y);該函數(shù)被C編譯器編譯后在庫中的名字為_foo,而C++編譯器則會(huì)產(chǎn)生像_foo_int_int之類的名字。C++提供了C連接交換指定符號extern“C”來解決名字匹配問題。
12、用變量a給出如下定義:
int a; //一個(gè)整型數(shù)
int *a; //一個(gè)指向整型數(shù)的指針
int **a; //一個(gè)指向指針的指針,它指向的指針是一個(gè)整型。
int a[10]; //一個(gè)有10個(gè)整型數(shù)的數(shù)組
int *a[10]; //一個(gè)有十個(gè)指針的數(shù)組,該指針是指向一個(gè)整型數(shù)。
(int*)a[10]; //一個(gè)指向有10整型數(shù)數(shù)組的指針。
int (*a)(int); //一個(gè)指向函數(shù)的指針,該函數(shù)有一個(gè)整型參數(shù),并返回一個(gè)整型值。
int (*a[10])(int); //一個(gè)有10個(gè)指針的數(shù)組,該指針指向一個(gè)函數(shù),并返回一個(gè)整型數(shù)。
12、關(guān)鍵字static的作用
- 1、在函數(shù)體內(nèi),一個(gè)唄聲明為static的變量在這一函數(shù)調(diào)用過程中維持值不變(只初始化一次)。
- 2、在模塊內(nèi),一個(gè)被聲明為static的變量可以被模塊內(nèi)所有的函數(shù)訪問,但是不能被模塊外的函數(shù)訪問。是一個(gè)本地的全局變量。
- 3、在模塊內(nèi),一個(gè)被聲明為static的函數(shù)可以被這一模塊內(nèi)的其他函數(shù)調(diào)用。那就是這個(gè)函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。
- 4、未經(jīng)初始化的靜態(tài)全局變量會(huì)被程序自動(dòng)初始化為0
在C++中的類成員前聲明static: - 類的靜態(tài)成員函數(shù)是屬于整個(gè)類而非類的對象,所以它沒有this指針,這就導(dǎo)致 了它僅能訪問類的靜態(tài)數(shù)據(jù)和靜態(tài)成員函數(shù)。
- 不能將靜態(tài)成員函數(shù)定義為虛函數(shù)。
- 靜態(tài)數(shù)據(jù)成員是靜態(tài)存儲(chǔ)的,所以必須對它進(jìn)行初始化
13、const關(guān)鍵字的作用?
用const修飾意味著是只讀的。
const int a; //a是一個(gè)常整型數(shù)
int const a; //同上
const int *a; //指向一個(gè)常整型數(shù)的指針(整型數(shù)不可修改,指針可修改)
int * const a; //指向一個(gè)整型數(shù)的常量指針(指針指向的值可以修改,但是指針本身不可修改)。
int const *a const; //指向常整數(shù)的常指針。(值和指針都不可修改)
//技巧:const在誰后面誰就不可修改,const在最前面則將其后移一位即可,二者等效
const有以下作用:
- 欲阻止一個(gè)變量被改變,可以使用const關(guān)鍵字。在定義該const變量時(shí),通常需要對它進(jìn)行初始化,因?yàn)橐院缶蜎]有機(jī)會(huì)再去改變它了。
- 對指針來說,可以指定指針本身為const,也可以指定指針?biāo)傅臄?shù)據(jù)為const,或二者同時(shí)指定為const
- 在一個(gè)函數(shù)聲明中,const可以修飾形參,表明它是一個(gè)輸入?yún)?shù),在函數(shù)內(nèi)部不能改變其值
- 對于類的成員函數(shù),若指定其為const類型,則表明其是一個(gè)常函數(shù),不能修改類的成員變量。const 在函數(shù)名后。 比如: void func() const
- 對于類的成員函數(shù),有時(shí)候必須指定其返回值為const類型,以使得其返回值不為“左值”.
const 在函數(shù)名前 const int func()。
14、指針與數(shù)組的區(qū)別:
訪問指針時(shí),先要找到指針變量本身的地址,從該地址再取到存放的指針值,然后對指針指向的對象進(jìn)行訪問,是間接訪問。訪問數(shù)組則是先找到數(shù)組變量符號代表的地址,對這個(gè)地址指向的對象進(jìn)行訪問,是直接訪問。
數(shù)組要么存放在靜態(tài)存儲(chǔ)區(qū)或者棧上。數(shù)組名對應(yīng)著一塊內(nèi)存,其地址與容量在生命周期內(nèi)保持不變。只有數(shù)組的內(nèi)容可以改變。當(dāng)數(shù)組作為函數(shù)的參數(shù)進(jìn)行傳遞時(shí),該數(shù)組自動(dòng)退化為同類型的指針。
指針可以隨時(shí)指向任意的內(nèi)存塊,特征是可變的。
15、如何判斷一個(gè)操作系統(tǒng)是16位還是32位,不能用sizeof()
int a = ~0;
if(a > 65535)
{
cout<<"32"<<endl;
}else{
cout<<"16"<<endl;
}
16、C和C++有什么不同?
從機(jī)制上看:C是面向過程的,C++是面向?qū)ο蟮模峁┝祟悺?/p>
17、進(jìn)程間通訊有哪些方式?
共享內(nèi)存、管道、socker、消息隊(duì)列。
18、new 、delete 、malloc、free關(guān)系。
delete會(huì)調(diào)用對象的析構(gòu)函數(shù),而free只會(huì)釋放內(nèi)存。new會(huì)調(diào)用構(gòu)造函數(shù)。malloc和free是C/C++的標(biāo)準(zhǔn)庫函數(shù),而new和delete是C++的運(yùn)算符。它們都可用于申請動(dòng)態(tài)內(nèi)存和釋放內(nèi)存。對于非內(nèi)部數(shù)據(jù)類型的對象而言,光用malloc/free無法滿足動(dòng)態(tài)對象的要求。對象在創(chuàng)建的同時(shí)要自動(dòng)執(zhí)行構(gòu)造函數(shù),對象在消亡之前要自動(dòng)執(zhí)行析構(gòu)函數(shù)。由于malloc/free是庫函數(shù)而不是運(yùn)算符,不在編譯器控制權(quán)限之內(nèi),不能夠把執(zhí)行構(gòu)造函數(shù)和析構(gòu)函數(shù)的任務(wù)強(qiáng)加于malloc/free。因此C++語言需要一個(gè)能完成動(dòng)態(tài)內(nèi)存分配和初始化工作的運(yùn)算符new,以及一個(gè)能完成清理與釋放內(nèi)存工作的運(yùn)算符delete。注意new/delete不是庫函數(shù)。
19、delete和delete []的區(qū)別
delete只會(huì)調(diào)用一次析構(gòu)函數(shù),而delete[]會(huì)調(diào)用每個(gè)成員的析構(gòu)函數(shù)。delete與new配套,delete []與new []配套。
20、子類析構(gòu)時(shí)要調(diào)用父類的析構(gòu)函數(shù)嗎?
析構(gòu)函數(shù)調(diào)用的次序是先派生類的析構(gòu)后基類的析構(gòu),也就是說在基類的的析構(gòu)調(diào)用的時(shí)候,派生類的信息已經(jīng)全部銷毀了。定義一個(gè)對象時(shí)先調(diào)用基類的構(gòu)造函數(shù)、然后調(diào)用派生類的構(gòu)造函數(shù);析構(gòu)的時(shí)候恰好相反:先調(diào)用派生類的析構(gòu)函數(shù)、然后調(diào)用基類的析構(gòu)函數(shù)。
21、多態(tài)、虛函數(shù)、純虛函數(shù)
多態(tài)是對于不同對象接收相同消息時(shí)產(chǎn)生不同的動(dòng)作。C++的多態(tài)性具體體現(xiàn)在運(yùn)行時(shí)和編譯時(shí)兩個(gè)方面。
運(yùn)行時(shí)的多態(tài)是通過虛函數(shù)與繼承來實(shí)現(xiàn)。
編譯時(shí)的多態(tài)體現(xiàn)在函數(shù)和運(yùn)算符的重載。
虛函數(shù):在基類中冠以關(guān)鍵字 virtual 的成員函數(shù)。 它提供了一種接口界面。允許在派生類中對基類的虛函數(shù)重新定義。
純虛函數(shù)的作用:在基類中為其派生類保留一個(gè)函數(shù)的名字,以便派生類根據(jù)需要對它進(jìn)行定義。作為接口而存在 純虛函數(shù)不具備函數(shù)的功能,一般不能直接被調(diào)用。從基類繼承來的純虛函數(shù),在派生類中仍是虛函數(shù)。如果一個(gè)類中至少有一個(gè)純虛函數(shù),那么這個(gè)類被稱為抽象類。抽象類中不僅包括純虛函數(shù),也可包括虛函數(shù)。抽象類必須用作派生其他類的基類,而不能用于直接創(chuàng)建對象實(shí)例。但仍可使用指向抽象類的指針支持運(yùn)行時(shí)多態(tài)性。
22、什么是“引用”?聲明和使用“引用”要注意哪些問題?
引用就是某個(gè)目標(biāo)變量的“別名”(alias),對應(yīng)用的操作與對變量直接操作效果完全相同。聲明一個(gè)引用的時(shí)候,切記要對其進(jìn)行初始化。引用聲明完畢后,相當(dāng)于目標(biāo)變量名有兩個(gè)名稱,即該目標(biāo)原名稱和引用名,不能再把該引用名作為其他變量名的別名。聲明一個(gè)引用,不是新定義了一個(gè)變量,它只表示該引用名是目標(biāo)變量名的一個(gè)別名,它本身不是一種數(shù)據(jù)類型,因此引用本身不占存儲(chǔ)單元,系統(tǒng)也不給引用分配存儲(chǔ)單元。不能建立數(shù)組的引用。
23、將“引用”作為函數(shù)參數(shù)有哪些特點(diǎn)?
- 傳遞引用給函數(shù)與傳遞指針的效果是一樣的。這時(shí),被調(diào)函數(shù)的形參就成為原來主調(diào)函數(shù)中的實(shí)參變量或?qū)ο蟮囊粋€(gè)別名來使用,所以在被調(diào)函數(shù)中對形參變量的操作就是對其相應(yīng)的目標(biāo)對象(在主調(diào)函數(shù)中)的操作。
- 使用引用傳遞函數(shù)的參數(shù),在內(nèi)存中并沒有產(chǎn)生實(shí)參的副本,它是直接對實(shí)參操作;而使用一般變量傳遞函數(shù)的參數(shù),當(dāng)發(fā)生函數(shù)調(diào)用時(shí),需要給形參分配存儲(chǔ)單元,形參變量是實(shí)參變量的副本;如果傳遞的是對象,還將調(diào)用拷貝構(gòu)造函數(shù)。因此,當(dāng)參數(shù)傳遞的數(shù)據(jù)較大時(shí),用引用比用一般變量傳遞參數(shù)的效率和所占空間都好。
- 使用指針作為函數(shù)的參數(shù)雖然也能達(dá)到與使用引用的效果,但是,在被調(diào)函數(shù)中同樣要給形參分配存儲(chǔ)單元,且需要重復(fù)使用"*指針變量名"的形式進(jìn)行運(yùn)算,這很容易產(chǎn)生錯(cuò)誤且程序的閱讀性較差;另一方面,在主調(diào)函數(shù)的調(diào)用點(diǎn)處,必須用變量的地址作為實(shí)參。而引用更容易使用,更清晰。
24、在什么時(shí)候需要使用“常引用”?
如果既要利用引用提高程序的效率,又要保護(hù)傳遞給函數(shù)的數(shù)據(jù)不在函數(shù)中被改變,就應(yīng)使用常引用。
25、將“引用”作為函數(shù)返回值類型的格式、好處和需要遵守的規(guī)則?
格式:類型標(biāo)識符 &函數(shù)名(形參列表及類型說明){ //函數(shù)體 }
好處:在內(nèi)存中不產(chǎn)生被返回值的副本;
注意事項(xiàng):
- 不能返回局部變量的引用。
- 不能返回函數(shù)內(nèi)部new分配的內(nèi)存的引用。
- 可以返回類成員的引用,但最好是const。
26、結(jié)構(gòu)與聯(lián)合有和區(qū)別?
結(jié)構(gòu)和聯(lián)合都是由多個(gè)不同的數(shù)據(jù)類型成員組成, 但在任何同一時(shí)刻, 聯(lián)合中只存放了一個(gè)被選中的成員(所有成員共用一塊地址空間), 而結(jié)構(gòu)的所有成員都存在(不同成員的存放地址不同)
對于聯(lián)合體的不同成員賦值, 將會(huì)對其它成員重寫, 原來成員的值就不存在了, 而對于結(jié)構(gòu)體的不同成員賦值是互不影響的
27、重載(overload)和重寫(overried,有的書也叫做“覆蓋”)的區(qū)別?
重載:是指允許存在多個(gè)同名函數(shù),而這些函數(shù)的參數(shù)表不同(或許參數(shù)個(gè)數(shù)不同,或許參數(shù)類型不同,或許兩者都不同)。
重寫:是指子類重新定義父類虛函數(shù)的方法。
28、哪幾種情況下只能用初始化列表,而不能用賦值?
當(dāng)類中含有const、reference 成員變量;基類的構(gòu)造函數(shù)都需要初始化表。
29、描述內(nèi)存分配方式以及它們的區(qū)別?
- 從靜態(tài)存儲(chǔ)區(qū)域分配。內(nèi)存在程序編譯的時(shí)候就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。例如全局變量,static 變量。
- 在棧上創(chuàng)建。在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集。
- 從堆上分配,亦稱動(dòng)態(tài)內(nèi)存分配。程序在運(yùn)行的時(shí)候用malloc 或new 申請任意多少的內(nèi)存,程序員自己負(fù)責(zé)在何時(shí)用free 或delete 釋放內(nèi)存。動(dòng)態(tài)內(nèi)存的生存期由程序員決定,使用非常靈活,但問題也最多。
30、請說出const與#define 相比,有何優(yōu)點(diǎn)?
const作用:定義常量、修飾函數(shù)參數(shù)、修飾函數(shù)返回值三個(gè)作用。被Const修飾的東西都受到強(qiáng)制保護(hù),可以預(yù)防意外的變動(dòng),能提高程序的健壯性。
const 常量有數(shù)據(jù)類型,而宏常量沒有數(shù)據(jù)類型。編譯器可以對前者進(jìn)行類型安全檢查。而對后者只進(jìn)行字符替換,沒有類型安全檢查,并且在字符替換可能會(huì)產(chǎn)生意料不到的錯(cuò)誤。
有些集成化的調(diào)試工具可以對const 常量進(jìn)行調(diào)試,但是不能對宏常量進(jìn)行調(diào)試。
31、引用與指針有什么區(qū)別?
- 引用必須被初始化,指針不必。
- 引用初始化以后不能被改變,指針可以改變所指的對象。
- 不存在指向空值的引用,但是存在指向空值的指針。
32、基類的析構(gòu)函數(shù)不是虛函數(shù),會(huì)帶來什么問題?
在實(shí)現(xiàn)多態(tài)時(shí),當(dāng)用基類操作派生類,在析構(gòu)時(shí)防止只析構(gòu)基類而不析構(gòu)派生類的狀況發(fā)生。避免內(nèi)存泄漏。
33、宏定義中的#、##、#@
在一個(gè)預(yù)處理器宏中的參數(shù)前面使用一個(gè)#,預(yù)處理器會(huì)把這個(gè)參數(shù)轉(zhuǎn)換為一個(gè)字符數(shù)組(字符串)。