1.數(shù)組名和指針的區(qū)別?
明確一點數(shù)組名不是指針,可以通過sizeof來驗證。其本質(zhì)是指代數(shù)組這樣一個數(shù)據(jù)結構。
數(shù)組名在表現(xiàn)很像const指針指針,不可以被改變(被賦值,++,--),可以用*來取對象,作為指針參數(shù),可以+整數(shù)
做為形參的數(shù)組名失去了其數(shù)據(jù)結構的本質(zhì)內(nèi)涵,其本質(zhì)是一個指針。
2.引用類型和指針的區(qū)別
從反匯編的角度看,引用的本質(zhì)是一個由編譯器管理的指針。其表現(xiàn)出來的語法特征和其所引用的對象一致。
作為函數(shù)參數(shù)時,和指針一樣,真正傳遞的是指針,而非對象的拷貝,較少了堆棧空間的使用,而且可以在函數(shù)體內(nèi)可以對所指的對象進行修改。
引用不可以被修改,以失去了指針的靈活性為代價,提高了程序安全性。
3.const總結
const的作用是希望通過對指定const屬性,保證變量不被錯誤修改,提高代碼的安全性。
修飾變量:變成了常量,不可以被修改,其他操作不受影響。編譯器在編譯時將用到該變量的地方替換成對應的值。與#define的替換相比,const保留了變量的類型屬性,可以做類型檢驗。
修飾指針:作用在指針本身,則該指針不能被修改(const指針),所以必須初始化;作用在其指向的對象上,則不能通過該指針修改其指向的對象;綁定常量的引用必須是指向常量的引用,指向常量的引用綁定的未必是常量。
修飾引用:不能夠通過該引用修改其綁定的對象。綁定常量的引用必須是指向常量的引用,指向常量的引用綁定的未必是常量。
修飾函數(shù):修飾隱式的this指針,將this指針設置為指向常量的指針,所以不能在函數(shù)體內(nèi)修改數(shù)據(jù)成員。
4.new/delete和malloc/free的區(qū)別
new/delete最終調(diào)用malloc/free來申請和釋放內(nèi)存。
c++封裝了new和delete完成為對象分配內(nèi)存,調(diào)用構造函數(shù),調(diào)用析構函數(shù),釋放內(nèi)存工作。
使用上比malloc和free更加方便,不用指定大??;引入異常bad_alloc。
new和delete通過調(diào)用operator?new和operator?delete來分配和釋放內(nèi)存,?而這兩個函數(shù)可以重載,為程序員自己實現(xiàn)內(nèi)存管理提供了方便。
5?struct和class的區(qū)別
在功能上基本沒有什么區(qū)別,class能做到事情struct基本能做。struct可以有成員函數(shù),可以繼承,可以有虛函數(shù)(實現(xiàn)多態(tài))。
區(qū)別在于默認的訪問控制:
6.const和define的區(qū)別
處理階段:const在編譯運行階段使用,define在編譯預處理階段展開
存儲方式:const需要分配內(nèi)存來存儲常量,而define不用分配內(nèi)存
安全性:編譯器會對const做類型檢查更加安全。
作用域:默認情況下const的作用范圍是文件內(nèi)部,多個文件共享需要使用extend?,#define的作用范圍是全局,多個文件定義define同名會報錯。
7.const和static的區(qū)別
內(nèi)存區(qū)域:
8.const和static在類中使用的注意事項
static成員不屬于任何對象,而是被他們共享。
靜態(tài)數(shù)據(jù)成員應該在類的外部定義。
因為沒有this指針,static成員函數(shù)不能用const修飾,也不能訪問非靜態(tài)成員。
9.c++內(nèi)存管理
10.內(nèi)聯(lián)函數(shù)
將函數(shù)指定為內(nèi)聯(lián)函數(shù)(inline),調(diào)用位置上內(nèi)聯(lián)展開,避免函數(shù)調(diào)用的開銷(堆棧維護,調(diào)整指令)。應用在規(guī)模小,流程直接,頻繁調(diào)用的函數(shù)。
將代碼放在符號表里,在調(diào)用點上展開。
內(nèi)聯(lián)說明只是向編譯器發(fā)出一個請求,編譯器可以忽略這個請求。編譯器優(yōu)化時,也可能將沒有inline說明的函數(shù)展開成內(nèi)聯(lián)函數(shù)。
11.多態(tài)和虛函數(shù)
C++通過虛函數(shù)實現(xiàn)動態(tài)綁定,也就是多態(tài)。
動態(tài)綁定是根據(jù)對象本身,而不是指針或引用的類型來確定具體調(diào)用的函數(shù)。具體實現(xiàn)是在對象中維護一個虛函數(shù)表指針,同個虛函數(shù)表中存儲了對象調(diào)用的函數(shù)的指針。
虛函數(shù)通過虛函數(shù)指針和虛函數(shù)表來實現(xiàn)動態(tài)綁定。
編譯器編譯時,為每個有虛函數(shù)的類生成一個虛函數(shù)表(一個一維數(shù)組),用來存儲該類的虛函數(shù)地址。
編譯器為每個對象提供一個指向虛表的指針。(在32位機器的內(nèi)存上看,是其前4個字節(jié),這也是為什么有虛函數(shù)的類型的sizeof多4個字節(jié)的原因)。
指向虛表的指針的初始化在構造函數(shù)中進行。
虛函數(shù)的位置,按照先后順序排列。
子類復制一份父類的虛函數(shù)表,替換重寫的虛函數(shù)地址,新加的虛函數(shù)依此放在表尾。
12.C++中的重載和重寫的區(qū)別:
重載:名稱相同參數(shù)不同。對操作相識的函數(shù),用相同的名字,方便程序員的理解,減輕起名字,記名字的負擔。
重寫:同名同參數(shù),虛函數(shù),子類將父類覆蓋掉(在虛函數(shù)表中覆蓋掉),即使通過強制類型轉(zhuǎn)化也不能訪問(對指針和引用而言)。
重定義:同名(參數(shù)可同可不同),基類中的函數(shù)被隱藏,子類對象無法直接訪問。
13.面向?qū)ο蟮娜齻€特征
繼承,多態(tài),封裝。
繼承:本質(zhì)是代碼復制。
多態(tài):多態(tài)和虛函數(shù)
封裝:將數(shù)據(jù)和和對操作封裝到放在一起。
14.析構函數(shù)一般寫成虛函數(shù)的原因?
delete父類指針時,可以調(diào)用對像真正的析構函數(shù)。否則可能會出錯,如子類中有指針類型,并且申請了內(nèi)存,這時就會造成內(nèi)存泄漏。
15.構造函數(shù)為什么一般不定義為虛函數(shù)
析構函數(shù)通過虛表來調(diào)用的,而指向虛表的指針是在構造函數(shù)中初始化的,這是個矛盾。
16.構造函數(shù)或者析構函數(shù)中調(diào)用虛函數(shù)會怎樣
結果上來看和調(diào)用普通函數(shù)無異。即基類調(diào)用基類的虛函數(shù),派生類調(diào)用派生類的虛函數(shù)。
17.純虛函數(shù)
18.引用是否能實現(xiàn)動態(tài)綁定,為什么引用可以實現(xiàn)
引用和指針的靜態(tài)類型和動態(tài)類型可以不一樣。
靜態(tài)類型:變量聲明時的類型或表達式生成的類型。編譯時已經(jīng)知道。
動態(tài)類型:變量或表達式表示的內(nèi)存的對象的類型。
19.深拷貝和淺拷貝的區(qū)別(舉例說明深拷貝的安全性)
在有指針成員的情況下,淺拷貝只是將指針指向已存在的內(nèi)存。即兩個對象的指針成員指向的是同一內(nèi)存區(qū)域。
深拷貝的做法是申請一個內(nèi)存復制一份,并將新對象指針指向備份區(qū)。
安全性:淺拷貝如果修改了指針指向的內(nèi)容,將對兩個對象都有影響。
20.對象復用的了解,零拷貝的了解
對象池:對象池通過對象復用的方式來避免重復創(chuàng)建對象,它會事先創(chuàng)建一定數(shù)量的對象放到池中,當用戶需要創(chuàng)建對象的時候,直接從對象池中獲取即可,用完對象之后再放回到對象池中,以便復用。
適用性:類的實例可重用。類的實例化過程開銷較大。類的實例化的頻率較高。
零拷貝:emplace_back
21.什么情況下會調(diào)用拷貝構造函數(shù)
(1)用類的一個對象去初始化另一個對象時
(2)當函數(shù)的形參是類的對象時(也就是值傳遞時),如果是引用傳遞則不會調(diào)用
(3)當函數(shù)的返回值是類的對象或引用時
22.結構體內(nèi)存對齊方式和為什么要進行內(nèi)存對齊?
23.內(nèi)存泄露的定義,如何檢測與避免?
申請的堆沒有被釋放,該內(nèi)存不能在被利用。
24.手寫實現(xiàn)智能指針類
25.調(diào)試程序的方法
26.C++的四種強制轉(zhuǎn)換(C++不是類型安全的)
static_cast?,?dynamic_cast?,?const_cast?,?reinterpret_cast
static_cast:可以實現(xiàn)C++中內(nèi)置基本數(shù)據(jù)類型之間的相互轉(zhuǎn)換。
const_cast:?操作不能在不同的種類間轉(zhuǎn)換。相反,它僅僅把一個它作用的表達式轉(zhuǎn)換成常量。它可以使一個本來不是const類型的數(shù)據(jù)轉(zhuǎn)換成const類型的,或者把const屬性去掉。
reinterpret_cast:有著和C風格的強制轉(zhuǎn)換同樣的能力。它可以轉(zhuǎn)化任何內(nèi)置的數(shù)據(jù)類型為其他任何的數(shù)據(jù)類型,也可以轉(zhuǎn)化任何指針類型為其他的類型。它甚至可以轉(zhuǎn)化內(nèi)置的數(shù)據(jù)類型為指針,無須考慮類型安全或者常量的情形。不到萬不得已絕對不用。
dynamic_cast:1)運行時處理,類型檢查;2)不能用于內(nèi)置的基本數(shù)據(jù)類型的強制轉(zhuǎn)換;3)轉(zhuǎn)換如果成功的話返回的是指向類的指針或引用,轉(zhuǎn)換失敗的話則會返回NULL(指針類型,如果是應用類型,拋出bad_cast異常);4)使用dynamic_cast進行轉(zhuǎn)換的,基類中一定要有虛函數(shù),否則編譯不通過;5)
27.遇到coredump要怎么調(diào)試
28.調(diào)試程序的方法
29.模板的用法與適用場景
模板是C++泛型編程的基礎。
使用:template??//關鍵字+<模板參數(shù)列表>
非類型模板參數(shù):
應用場景:除了參數(shù)類型不一樣外,其他的內(nèi)容全部一樣(函數(shù)體),用模板,而不是每一個類型都寫一個函數(shù)。
特化:模板的一個獨立的定義,其中一個或多個參數(shù)被指定為特定的類型。通用模板不能適應所有情況。(特殊情況特殊處理)
30.成員初始化列表的概念,為什么用成員初始化列表會快一些
概念:以一個冒號開始,接著是以逗號分隔的數(shù)據(jù)成員列表,每個數(shù)據(jù)成員后面跟一個放在括號中的初始化式,對成員進行初始化。
效率:構造函數(shù)之前執(zhí)行默認初始化。而成員初始化列表,可以立即初始化,所以更快些。
成員是const對象和引用必須初始化。
31.虛繼承
為了避免一個類多次集成一個基類而包含多份基類的拷貝,使用虛繼承機制。(基于多重繼承)
32.函數(shù)調(diào)用過程(堆棧圖)
