二十万字C/C++、嵌入式软开面试题全集宝典九
目錄
161、 空類
162、 空類會(huì)默認(rèn)添加哪些東西?怎么寫?
163、 標(biāo)準(zhǔn)庫是什么?
164、 const char* 與string之間的關(guān)系,傳遞參數(shù)問題?
165、 char * 與char[]
166、 sizeof 和strlen 的區(qū)別
167、 針對(duì)char*和char[]求sizeof()
168、 new、delete、operator new、operator delete、placement new、placement delete
169、 空類的大小是多少?為什么?
170、 計(jì)算下面幾個(gè)類的大小
171、 類對(duì)象的大小
172、 函數(shù)傳遞參數(shù)的幾種方式
173、 將“引用”作為函數(shù)參數(shù)有哪些特點(diǎn)?
174、 你什么情況用指針當(dāng)參數(shù),什么時(shí)候用引用,為什么?
175、 大內(nèi)存申請(qǐng)時(shí)候選用哪種?C++變量存在哪?變量的大小存在哪?符號(hào)表存在哪?
176、 為什么會(huì)有大端小端,htol這一類函數(shù)的作用
177、 靜態(tài)函數(shù)能定義為虛函數(shù)嗎?常函數(shù)?
178、 this指針調(diào)用成員變量時(shí),堆棧會(huì)發(fā)生什么變化?
179、 設(shè)計(jì)一個(gè)類計(jì)算子類的個(gè)數(shù)
180、 怎么快速定位錯(cuò)誤出現(xiàn)的地方
?
161、 空類
對(duì)于空類,編譯器不會(huì)生成任何的成員函數(shù),只會(huì)生成1個(gè)字節(jié)的占位符。在C++語言中的確規(guī)定了空結(jié)構(gòu)體和空類所占內(nèi)存大小為1,而C語言中空類和空結(jié)構(gòu)體占用的大小是0(在gcc中測試為0,其他編譯器不一定)。為什么C++會(huì)有這樣的規(guī)定呢?
原來,C++語言標(biāo)準(zhǔn)中規(guī)定了這樣一個(gè)原則:" no object shall have the same address in memory as any other variable",即任何不同的對(duì)象不能擁有相同的內(nèi)存地址。如果空類對(duì)象大小為0,那么此類數(shù)組中的各個(gè)對(duì)象的地址將會(huì)一致,明顯違反了此原則。
lsy注1:其實(shí)數(shù)組這個(gè)東西,往后找都是靠在第一個(gè)的基礎(chǔ)上便宜,最后這句話就是說,你如果有多個(gè)類,都為0的話,他們就會(huì)覆蓋。這也是數(shù)組的下標(biāo)為什么從0開始的原因。
162、 空類會(huì)默認(rèn)添加哪些東西?怎么寫?
class Emptyclass {
}
1、缺省構(gòu)造函數(shù)
Emptyclass();
2、析構(gòu)函數(shù)
~Emptyclass();
3、拷貝構(gòu)造函數(shù)
Emptyclass(const Emptyclass&);
4、賦值運(yùn)算符
Emptyclass operator=(const Emptyclass&);
5、取地址運(yùn)算符
Emptyclass* operator&();
6、取地址運(yùn)算符 const
const Emptyclass* operator&() const;
163、 標(biāo)準(zhǔn)庫是什么?
1.C++ 標(biāo)準(zhǔn)庫可以分為兩部分:
標(biāo)準(zhǔn)函數(shù)庫:這個(gè)庫是由通用的、獨(dú)立的、不屬于任何類的函數(shù)組成的。函數(shù)庫繼承自 C 語言。
面向?qū)ο箢悗?#xff1a;這個(gè)庫是類及其相關(guān)函數(shù)的集合。
1.輸入/輸出 I/O、字符串和字符處理、數(shù)學(xué)、時(shí)間、日期和本地化、動(dòng)態(tài)分配、其他、寬字符函數(shù)
2.標(biāo)準(zhǔn)的 C++ I/O 類、String 類、數(shù)值類、STL 容器類、STL 算法、STL 函數(shù)對(duì)象、STL 迭代器、STL 分配器、本地化庫、異常處理類、雜項(xiàng)支持庫
164、 const char* 與string之間的關(guān)系,傳遞參數(shù)問題?
1.string是c++標(biāo)準(zhǔn)庫里面其中一個(gè),封裝了對(duì)字符串的操作,實(shí)際操作過程我們可以用const char*給string類初始化
2.三者的轉(zhuǎn)化關(guān)系如下所示:
○1string轉(zhuǎn)const char*
string s = “abc”;
const char* c_s = s.c_str();
○2const char* 轉(zhuǎn)string,直接賦值即可
const char* c_s = “abc”; string s(c_s);
○3string 轉(zhuǎn)char*
string s = “abc”;
char* c;
const int len = s.length();
c = new char[len+1];
strcpy(c,s.c_str());
○4char* 轉(zhuǎn)string
char* c = “abc”;
string s(c);
○5const char* 轉(zhuǎn)char*
const char* cpc = “abc”;
char* pc = new char[strlen(cpc)+1];
strcpy(pc,cpc);
○6char* 轉(zhuǎn)const char*,直接賦值即可
char* pc = “abc”;
const char* c;
c = pc;
165、 char * 與char[]
char*指針定義的字符串只能讀不能修改;char []定義的字符串可讀可修改。
這是因?yàn)閏har *a = “abcd”; 此時(shí)"abcd"存放在內(nèi)存的常量區(qū)。常量區(qū)只能讀,而不可以修改。(而且這樣定義是不可以的,需要這樣寫:const char *a = “abcd”)。
而char a[20] = “abcd”; 此時(shí) "abcd"存放在棧區(qū)。可以通過指針去訪問和修改數(shù)組內(nèi)容。
166、 sizeof 和strlen 的區(qū)別
1.strlen計(jì)算字符串的具體長度(只能是字符串),不包括字符串結(jié)束符。返回的是字符個(gè)數(shù)。
2.sizeof計(jì)算聲明后所占的內(nèi)存數(shù)(字節(jié)大小,如果是字符串,包含/n),不是實(shí)際長度。
3.sizeof是一個(gè)取字節(jié)運(yùn)算符,而strlen是個(gè)函數(shù)。
4.sizeof的返回值=字符個(gè)數(shù)*字符所占的字節(jié)數(shù),字符實(shí)際長度小于定義的長度,此時(shí)字符個(gè)數(shù)就等于定義的長度。若未給出定義的大小,分類討論,對(duì)于字符串?dāng)?shù)組,字符大小等于實(shí)際的字符個(gè)數(shù)+1;對(duì)于整型數(shù)組,字符個(gè)數(shù)為實(shí)際的字符個(gè)數(shù)。字符串每個(gè)字符占1個(gè)字節(jié),整型數(shù)據(jù)每個(gè)字符占的字節(jié)數(shù)需根據(jù)系統(tǒng)的位數(shù)類確定,32位占4個(gè)字節(jié)。
5.sizeof可以用類型做參數(shù),strlen只能用char*做參數(shù),且必須以‘\0’結(jié)尾,sizeof還可以用函數(shù)做參數(shù);
6.數(shù)組做sizeof的參數(shù)不退化,傳遞給strlen就退化為指針;
167、 針對(duì)char*和char[]求sizeof()
char *a;
char b[5];
sizeof(a) = 8 ; // 64位系統(tǒng),8代表的是指針的大小,指針占8字節(jié)
sizeof(b) = 5 ; // 計(jì)算字符串?dāng)?shù)組的結(jié)果是真實(shí)的字符數(shù)組大小
168、 new、delete、operator new、operator delete、placement new、placement delete
1.new operator
new operator 完成了兩件事情:用于申請(qǐng)內(nèi)存和初始化對(duì)象。
例如:string* ps = new string("abc");
2.operator new
operator new 類似于C語言中的malloc,只是負(fù)責(zé)申請(qǐng)內(nèi)存。
例如:void* buffer = operator new(sizeof(string)); 注意這里new前要有個(gè)operator。
3.placement new用于在給定的內(nèi)存中初始化對(duì)象。
例如:void* buffer = operator new(sizeof(string));buffer = new(buffer) string("abc"); 調(diào)用了placement new,在buffer所指向的內(nèi)存中創(chuàng)建了一個(gè)string類型的對(duì)象并且初始值為“abc”。
4.因此可以看出:new operator 可以分解operator new 和 placement new兩個(gè)動(dòng)作,是 operator new 和 placement new 的結(jié)合。與new對(duì)應(yīng)的delete沒有 placement delete 語法,它只有兩種,分別是delete operator 和 operator delete。delete operator 和 new operator 對(duì)應(yīng),完成析構(gòu)對(duì)象和釋放內(nèi)存的操作。而 operator delete 只是用于內(nèi)存的釋放,與C語言中的free相似。
169、 空類的大小是多少?為什么?
1.C++空類的大小不為0,不同編譯器設(shè)置不一樣,vs設(shè)置為1(作為一個(gè)標(biāo)記);
2.C++標(biāo)準(zhǔn)指出,不允許一個(gè)對(duì)象(當(dāng)然包括類對(duì)象)的大小為0,不同的對(duì)象不能具有相同的地址;
3.帶有虛函數(shù)的C++類大小不為1,因?yàn)槊恳粋€(gè)對(duì)象會(huì)有一個(gè)vptr指向虛函數(shù)表,具體大小根據(jù)指針大小確定(32位系統(tǒng)指針大小為4字節(jié),64位系統(tǒng)指針大小為8字節(jié));
3.C++中要求對(duì)于類的每個(gè)實(shí)例都必須有獨(dú)一無二的地址,那么編譯器自動(dòng)為空類分配一個(gè)字節(jié)大小,這樣便保證了每個(gè)實(shí)例均有獨(dú)一無二的內(nèi)存地址。
170、 計(jì)算下面幾個(gè)類的大小
1.class A{}; sizeof(A) = 1; //空類在實(shí)例化時(shí)得到?個(gè)獨(dú)???的地址,所以為 1。
2.class A{virtual Fun(){} }; sizeof(A) = 4(32bit)/8(64bit) //當(dāng) C++ 類中有虛函數(shù)的時(shí)候,會(huì)有?個(gè)指向虛函數(shù)表的指針(vptr)
class A{static int a; }; sizeof(A) = 1;
class A{int a; }; sizeof(A) = 4;
class A{static int a; int b; }; sizeof(A) = 4;
171、 類對(duì)象的大小
1.類的非靜態(tài)成員變量大小,靜態(tài)成員不占據(jù)類的空間,成員函數(shù)也不占據(jù)類的空間大小;
2.內(nèi)存對(duì)齊另外分配的空間大小,類內(nèi)的數(shù)據(jù)也是需要進(jìn)行內(nèi)存對(duì)齊操作的;
3.虛函數(shù)的話,會(huì)在類對(duì)象插入vptr指針,加上指針大小;
4.當(dāng)該該類是某類的派生類,那么派生類繼承的基類部分的數(shù)據(jù)成員也會(huì)存在在派生類中的空間中,也會(huì)對(duì)派生類進(jìn)行擴(kuò)展。
172、 函數(shù)傳遞參數(shù)的幾種方式
1、值傳遞:形參是實(shí)參的拷?,函數(shù)內(nèi)部對(duì)形參的操作并不會(huì)影響到外部的實(shí)參。
2、指針傳遞:也是值傳遞的?種?式,形參是指向?qū)崊⒌刂返闹羔?#xff0c;當(dāng)對(duì)形參的指向操作時(shí),就相當(dāng)于對(duì)實(shí)參本身進(jìn)?操作。
3、引?傳遞:實(shí)際上就是把引?對(duì)象的地址放在了開辟的棧空間中,函數(shù)內(nèi)部對(duì)形參的任何操作可以直接映射到外部的實(shí)參上?。
173、 將“引用”作為函數(shù)參數(shù)有哪些特點(diǎn)?
1.傳遞引用給函數(shù)與傳遞指針的效果是一樣的。這時(shí),被調(diào)函數(shù)的形參就成為原來主調(diào)函數(shù)中的實(shí)參變量或?qū)ο蟮囊粋€(gè)別名來使用,所以在被調(diào)函數(shù)中對(duì)形參變量的操作就是對(duì)其相應(yīng)的目標(biāo)對(duì)象(在主調(diào)函數(shù)中)的操作。
2.使用引用傳遞函數(shù)的參數(shù),在內(nèi)存中并沒有產(chǎn)生實(shí)參的副本,它是直接對(duì)實(shí)參操作;而使用一般變量傳遞函數(shù)的參數(shù),當(dāng)發(fā)生函數(shù)調(diào)用時(shí),需要給形參分配存儲(chǔ)單元,形參變量是實(shí)參變量的副本;如果傳遞的是對(duì)象,還將調(diào)用拷貝構(gòu)造函數(shù)。因此,當(dāng)參數(shù)傳遞的數(shù)據(jù)較大時(shí),用引用比用一般變量傳遞參數(shù)的效率和所占空間都好。
3.使用指針作為函數(shù)的參數(shù)雖然也能達(dá)到與使用引用的效果,但是,在被調(diào)函數(shù)中同樣要給形參分配存儲(chǔ)單元,且需要重復(fù)使用"*指針變量名"的形式進(jìn)行運(yùn)算,這很容易產(chǎn)生錯(cuò)誤且程序的閱讀性較差;另一方面,在主調(diào)函數(shù)的調(diào)用點(diǎn)處,必須用變量的地址作為實(shí)參。而引用更容易使用,更清晰。
174、 你什么情況用指針當(dāng)參數(shù),什么時(shí)候用引用,為什么?
1.使用引用參數(shù)的主要原因有兩個(gè):
程序員能修改調(diào)用函數(shù)中的數(shù)據(jù)對(duì)象
通過傳遞引用而不是整個(gè)數(shù)據(jù)對(duì)象,可以提高程序的運(yùn)行速度
2.一般的原則:
○1對(duì)于使用引用的值而不做修改的函數(shù):
如果數(shù)據(jù)對(duì)象很小,如內(nèi)置數(shù)據(jù)類型或者小型結(jié)構(gòu),則按照值傳遞;
如果數(shù)據(jù)對(duì)象是數(shù)組,則使用指針(唯一的選擇),并且指針聲明為指向const的指針;
如果數(shù)據(jù)對(duì)象是較大的結(jié)構(gòu),則使用const指針或者引用,已提高程序的效率。這樣可以節(jié)省結(jié)構(gòu)所需的時(shí)間和空間;
如果數(shù)據(jù)對(duì)象是類對(duì)象,則使用const引用(傳遞類對(duì)象參數(shù)的標(biāo)準(zhǔn)方式是按照引用傳遞);
○2對(duì)于修改函數(shù)中數(shù)據(jù)的函數(shù):
如果數(shù)據(jù)是內(nèi)置數(shù)據(jù)類型,則使用指針
如果數(shù)據(jù)對(duì)象是數(shù)組,則只能使用指針
如果數(shù)據(jù)對(duì)象是結(jié)構(gòu),則使用引用或者指針
如果數(shù)據(jù)是類對(duì)象,則使用引用
175、 大內(nèi)存申請(qǐng)時(shí)候選用哪種?C++變量存在哪?變量的大小存在哪?符號(hào)表存在哪?
1.大內(nèi)存申請(qǐng)時(shí),采用堆申請(qǐng)空間,用new申請(qǐng);
2.不同的變量存儲(chǔ)在不同的地方,局部變量、全局變量、靜態(tài)變量;
3.C++對(duì)變量名不作存儲(chǔ),在匯編以后不會(huì)出現(xiàn)變量名,變量名作用只是用于方便編譯成匯編代碼,是給編譯器看的,是方便人閱讀的。
176、 為什么會(huì)有大端小端,htol這一類函數(shù)的作用
1.這是因?yàn)樵谟?jì)算機(jī)系統(tǒng)中,我們是以字節(jié)為單位的,每個(gè)地址單元都對(duì)應(yīng)著一個(gè)字節(jié),一個(gè)字節(jié)為8bit。但是在C語言中除了8bit的char之外,還有16bit的short型,32bit的long型(要看具體的編譯器),另外,對(duì)于位數(shù)大于8位的處理器,例如16位或者32位的處理器,由于寄存器寬度大于一個(gè)字節(jié),那么必然存在著一個(gè)如何將多個(gè)字節(jié)安排的問題。因此就導(dǎo)致了大端存儲(chǔ)模式和小端存儲(chǔ)模式。例如一個(gè)16bit的short型x,在內(nèi)存中的地址為0x0010,x的值為0x1122,那么0x11為高字節(jié),0x22為低字節(jié)。對(duì)于 大端模式,就將0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,剛好相反。我們常用的X86結(jié)構(gòu)是小端模式,而KEILC51則為大端模式。很多的ARM,DSP都為小端模式。有些ARM處理器還可以由硬件來選擇是大端模式還是小端模式。
177、 靜態(tài)函數(shù)能定義為虛函數(shù)嗎?常函數(shù)?
1.static成員不屬于任何類對(duì)象或類實(shí)例,所以即使給此函數(shù)加上virutal也是沒有任何意義的。
2.靜態(tài)與非靜態(tài)成員函數(shù)之間有一個(gè)主要的區(qū)別。那就是靜態(tài)成員函數(shù)沒有this指針(因?yàn)閠his指針是指向?qū)ο蟮?#xff0c;而靜態(tài)成員函數(shù)屬于類,所以沒有)。虛函數(shù)依靠vptr和vtable來處理。vptr是一個(gè)指針,在類的構(gòu)造函數(shù)中創(chuàng)建生成,并且只能用this指針來訪問它,因?yàn)樗穷惖囊粋€(gè)成員,并且vptr指向保存虛函數(shù)地址的vtable.對(duì)于靜態(tài)成員函數(shù),它沒有this指針,所以無法訪問vptr. 這就是為何static函數(shù)不能為virtual.虛函數(shù)的調(diào)用關(guān)系:this -> vptr -> vtable ->virtual function
178、 this指針調(diào)用成員變量時(shí),堆棧會(huì)發(fā)生什么變化?
1.當(dāng)在類的非靜態(tài)成員函數(shù)訪問類的非靜態(tài)成員時(shí),編譯器會(huì)自動(dòng)將對(duì)象的地址傳給作為隱含參數(shù)傳遞給函數(shù),這個(gè)隱含參數(shù)就是this指針。
2.即使你并沒有寫this指針,編譯器在鏈接時(shí)也會(huì)加上this的,對(duì)各成員的訪問都是通過this的。例如你建立了類的多個(gè)對(duì)象時(shí),在調(diào)用類的成員函數(shù)時(shí),你并不知道具體是哪個(gè)對(duì)象在調(diào)用,此時(shí)你可以通過查看this指針來查看具體是哪個(gè)對(duì)象在調(diào)用。
3.this指針首先入棧,然后成員函數(shù)的參數(shù)從右向左進(jìn)行入棧,最后函數(shù)返回地址入棧。
179、 設(shè)計(jì)一個(gè)類計(jì)算子類的個(gè)數(shù)
1.為類設(shè)計(jì)一個(gè)static靜態(tài)變量count作為計(jì)數(shù)器;
2.類定義結(jié)束后初始化count;
3.在構(gòu)造函數(shù)中對(duì)count進(jìn)行+1;
4.設(shè)計(jì)拷貝構(gòu)造函數(shù),在進(jìn)行拷貝構(gòu)造函數(shù)中進(jìn)行count +1,操作;
5.設(shè)計(jì)復(fù)制構(gòu)造函數(shù),在進(jìn)行復(fù)制函數(shù)中對(duì)count+1操作;
6.在析構(gòu)函數(shù)中對(duì)count進(jìn)行-1;
180、 怎么快速定位錯(cuò)誤出現(xiàn)的地方
1.如果是簡單的錯(cuò)誤,可以直接雙擊錯(cuò)誤列表里的錯(cuò)誤項(xiàng)或者生成輸出的錯(cuò)誤信息中帶行號(hào)的地方就可以讓編輯窗口定位到錯(cuò)誤的位置上。
2.對(duì)于復(fù)雜的模板錯(cuò)誤,最好使用生成輸出窗口。多數(shù)情況下出發(fā)錯(cuò)誤的位置是最靠后的引用位置。如果這樣確定不了錯(cuò)誤,就需要先把自己寫的代碼里的引用位置找出來,然后逐個(gè)分析了。
總結(jié)
以上是生活随笔為你收集整理的二十万字C/C++、嵌入式软开面试题全集宝典九的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PyQt5中使用代码实现嵌套布局
- 下一篇: yy神曲url解析php_php解析ur