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