面試常見問題-c++

1. 聲明與定義的區(qū)別

變量定義:為變量分配存儲空間端姚,可以為變量指定初始值
變量聲明:向程序表明存在一個(gè)變量
定義也是聲明,加上了extern的聲明不是定義讹俊,表明變量定義在其他地方
在一個(gè)程序中垦沉,變量只能定義一次,可以聲明多次

函數(shù)定義:帶有{}的是定義
函數(shù)聲明:沒有{}的是聲明

int a; // 定義
int b = 0; // 定義劣像,初始化
extern int c; // 聲明乡话,非定義
int double funca(int a, int b); // 聲明函數(shù)
int double funcb(int a, int b){return max(a, b);} // 定義函數(shù)
extern double funcc(int a, int b); // 聲明函數(shù)

2. extern和static的區(qū)別

extern用于聲明變量或函數(shù),并且表明這個(gè)變量或函數(shù)的定義在其他地方
static用于定義靜態(tài)變量或函數(shù)耳奕,并且該變量或函數(shù)只對當(dāng)前源文件可見

3. static的作用

當(dāng)使用static定義一個(gè)全局變量或函數(shù)時(shí)绑青,這個(gè)全局變量或函數(shù)成為靜態(tài)全局變量或靜態(tài)全局函數(shù)诬像,它只對當(dāng)前源文件可見,會對其他源文件隱藏

當(dāng)使用static定義一個(gè)局部變量時(shí)闸婴,這個(gè)局部變量成為靜態(tài)局部變量坏挠,它的存儲區(qū)域不在棧上而在靜態(tài)數(shù)據(jù)區(qū),當(dāng)這個(gè)局部執(zhí)行結(jié)束時(shí)邪乍,靜態(tài)局部變量的存儲區(qū)域不會被釋放降狠,當(dāng)?shù)诙卧L問到這個(gè)靜態(tài)局部變量時(shí),它的值不會變化

當(dāng)使用static定義類中的成員變量或函數(shù)時(shí)庇楞,這個(gè)成員變量或函數(shù)會成為整個(gè)類的成員榜配,而不屬于某一個(gè)具體的對象

static會對變量進(jìn)行自動初始化

4. x = x + 1, x += 1, x++的效率

第一個(gè)效率最低,因?yàn)槭紫纫x取右邊x的地址吕晌,然后加一操作蛋褥,然后讀取左邊x的地址,然后傳值給它

第二個(gè)效率第二低睛驳,它首先讀取x的地址烙心,然后加一操作,然后直接傳值給x

第三個(gè)效率最高乏沸,它首先讀取x的地址淫茵,然后直接x自增加一

5. const和宏定義的區(qū)別

const和define都可以用來定義一個(gè)常量
define在預(yù)處理階段對程序代碼進(jìn)行字面上的替換,沒有數(shù)據(jù)類型蹬跃,不會進(jìn)行類型檢查匙瘪;const定義一個(gè)只讀變量,有數(shù)據(jù)類型炬转,有類型檢查
由于define是做字面替換辆苔,有多少地方使用就替換多少次,宏常量在內(nèi)存中有多個(gè)備份扼劈;const定義的變量存儲在靜態(tài)數(shù)據(jù)區(qū)驻啤,使用的時(shí)候去靜態(tài)數(shù)據(jù)區(qū)調(diào)用,只有一個(gè)備份

6. strcpy和memcpy的區(qū)別

strcpy只用于字符串的復(fù)制荐吵,memcpy可以復(fù)制任意類型
strcpy在復(fù)制時(shí)不需要指定長度骑冗,遇到字符串結(jié)束符就結(jié)束,可能發(fā)生溢出先煎,memcpy需要指定復(fù)制的長度

char* strcpy(char* dest, const char* src){
    if((src == NULL) || (dest == NULL)) // 判斷是否有效
        return NULL;
    strdest = dest; // 保存dest首地址
    while(*src != 0){
        *dest = *src;
        dest++;
        src++;
    } // 逐個(gè)復(fù)制
    return strdest;
void* memcpy(void* dest, const void* src, size_t size){
    if((src == NULL) || (dest == NULL)) // 判斷是否有效
        return NULL;
    memdest = dest;
    while(size--){
        *dest = *src;
        dest++;
        src++;
    }
    return memdest;
}

7. new和malloc的區(qū)別

new是c++的關(guān)鍵字贼涩,malloc是c的庫函數(shù)
new對應(yīng)的是delete,malloc對應(yīng)的是free
在動態(tài)分配內(nèi)存的時(shí)候薯蝎,new不需要指定具體分配內(nèi)存的大小遥倦,編譯器會自動根據(jù)類型計(jì)算,malloc需要顯式指出分配內(nèi)存大小
new返回的是對應(yīng)類型的指針占锯,malloc返回的是void*
new分配失敗會拋出異常袒哥,malloc分配失敗返回NULL
new可以自動初始化缩筛,malloc需要用戶另外初始化

8. 構(gòu)造函數(shù)和析構(gòu)函數(shù)可不可以是虛函數(shù)

構(gòu)造函數(shù)不能是虛函數(shù)
虛函數(shù)調(diào)用需要用到虛函數(shù)指針,虛函數(shù)指針存放在對象的內(nèi)存空間中堡称,如果將構(gòu)造函數(shù)聲明為虛函數(shù)瞎抛,則對象還沒創(chuàng)建時(shí),沒有虛函數(shù)指針却紧,無法調(diào)用虛函數(shù)桐臊,無法調(diào)用構(gòu)造函數(shù)

析構(gòu)函數(shù)可以是虛函數(shù)
當(dāng)存在基類和派生類的時(shí)候,最好將析構(gòu)函數(shù)聲明為虛函數(shù)晓殊。如果有一個(gè)基類指針指向一個(gè)派生類對象断凶,并且析構(gòu)函數(shù)不是虛函數(shù),當(dāng)delete基類指針時(shí)巫俺,就會調(diào)用基類的析構(gòu)函數(shù)懒浮,派生類的新部分不會被釋放;如果將析構(gòu)函數(shù)聲明為虛函數(shù)识藤,當(dāng)delete基類指針時(shí),就會調(diào)用派生類的析構(gòu)函數(shù)次伶,釋放派生類對象的所有空間

9. 如何限制一個(gè)類只能在堆/棧上分配空間

只能在堆上分配空間:只能用new分配痴昧,不能直接調(diào)用類的構(gòu)造函數(shù)
將構(gòu)造函數(shù)和析構(gòu)函數(shù)設(shè)置為protected,然后寫新的public的函數(shù)來構(gòu)造和析構(gòu)冠王,用來構(gòu)造的函數(shù)通過new來構(gòu)造對象赶撰,用來析構(gòu)的函數(shù)通過delete來銷毀對象

class A{
protected:
    A(){}
    ~A(){}
public:
    static A* create(){
        return new A();
    }
    void destroy(){
        delete this;
    }
};

只能在棧上分配空間:不能用new分配,將operator new()設(shè)置成私有

class A{
public:
    A(){}
    ~A(){}
private:
    A* operator new(size_t t){}
    void operator delete(void* ptr){}
};

10. 拷貝構(gòu)造函數(shù)能夠使用值傳遞

不能柱彻。如果使用值傳遞豪娜,在調(diào)用拷貝構(gòu)造函數(shù)的時(shí)候,形參需要調(diào)用拷貝構(gòu)造函數(shù)給實(shí)參傳值哟楷,這樣就會無限調(diào)用拷貝構(gòu)造函數(shù)瘤载,無法完成拷貝

11. C++的內(nèi)存分配

程序占用內(nèi)存分為以下幾個(gè)部分:
棧區(qū):由編譯器自動分配釋放,存放運(yùn)行時(shí)函數(shù)中的參數(shù)卖擅、局部變量鸣奔、返回值、返回地址等惩阶,操作類似數(shù)據(jù)結(jié)構(gòu)中的棧挎狸,后進(jìn)先出
堆區(qū):由用戶通過new、malloc分配和delete断楷、free釋放锨匆,分配類似鏈表,可能會產(chǎn)生碎片冬筒,如果在堆上分配了空間忘了釋放恐锣,會造成內(nèi)存泄漏
全局區(qū):存放全局變量茅主、靜態(tài)數(shù)據(jù)、const常量侥蒙,分為未初始化區(qū)bss和已初始化區(qū)data
文字常量區(qū):存放常量字符串
代碼區(qū):存放代碼

12. 棧和堆的區(qū)別

管理方式不同:棧由編譯器自動分配和釋放暗膜,堆是程序員手動申請和釋放
空間大小不同:棧比堆小很多
生長方向不同:棧往下長,朝著內(nèi)存地址減小的方向鞭衩,堆往上長学搜,朝著內(nèi)存地址增大的方向
是否產(chǎn)生碎片:棧后進(jìn)先出,彈出一個(gè)元素前论衍,上一個(gè)元素已經(jīng)彈出瑞佩,不會產(chǎn)生碎片
分配效率不同:棧的分配效率比堆高,因?yàn)闂S袑iT的結(jié)構(gòu)存放棧頂?shù)刂放魈ǎ瑝簵3鰲1容^快炬丸,堆的分配要搜索能夠使用的內(nèi)存,比較慢

13. 動態(tài)內(nèi)存分配

有兩種數(shù)據(jù)結(jié)構(gòu)存放內(nèi)存使用情況:
空閑分區(qū)表:每個(gè)空閑分區(qū)對應(yīng)一個(gè)表項(xiàng)蜒蕾,含有分區(qū)號稠炬、分區(qū)大小、分區(qū)起始地址等信息
空閑分區(qū)鏈:每個(gè)分區(qū)的起始和末尾有指向上一個(gè)和下一個(gè)空閑分區(qū)指針咪啡,起始部分還存有分區(qū)大小等信息

動態(tài)分配算法:
首次適應(yīng):從頭到尾找到一個(gè)適合的分區(qū)首启,查找耗時(shí),實(shí)現(xiàn)簡單
最佳適應(yīng):優(yōu)先使用更小的分區(qū)撤摸,保留更多的大分區(qū)塊毅桃,滿足大進(jìn)程需求
最壞適應(yīng):優(yōu)先使用更大的分區(qū),減少難以利用的小碎片
鄰近適應(yīng):從當(dāng)前位置查找適合的分區(qū)准夷,查找簡單钥飞,實(shí)現(xiàn)簡單

伙伴內(nèi)存管理:
將空閑分區(qū)塊根據(jù)大小分組,2^i大小的分為一組衫嵌,每組形成一個(gè)鏈表读宙,分配時(shí)直接到相應(yīng)的鏈表查找有無空閑塊
如果沒有,就到更大的空閑塊鏈表查找渐扮,找到后將其拆分论悴,剩余的空閑塊插入到相應(yīng)大小的鏈表
釋放的時(shí)候,如果相鄰的位置有空閑塊墓律,就合并后插入到更大的內(nèi)存塊鏈表

14. struct的字節(jié)對齊

成員變量的起始地址為其長度的整數(shù)倍膀估,結(jié)構(gòu)體的總大小為其最大長度成員變量大小的整數(shù)倍
定義變量的順序不一樣,整個(gè)結(jié)構(gòu)體的大小會不一樣

struct A{
    char a;
    short b;
    int c;
};

sizeof(A) = 8

struct B{
    char a;
    int b;
    short c;
};

sizeof(B) = 12

15. 智能指針

智能指針能夠自動釋放它所指向的對象
有三種智能指針:unique_ptr耻讽、shared_ptr察纯、weak_ptr

unique pointer獨(dú)占它所指向的對象,shared pointer允許多個(gè)指針指向同一個(gè)對象,weak pointer是弱引用饼记,指向shared pointer管理的對象香伴,用來解決shared pointer中會出現(xiàn)的死鎖現(xiàn)象

每一個(gè)shared pointer都有一個(gè)關(guān)聯(lián)的計(jì)數(shù)器,統(tǒng)計(jì)它所指向?qū)ο蟮囊糜?jì)數(shù)具则,當(dāng)引用計(jì)數(shù)變?yōu)榱愕臅r(shí)候即纲,就會釋放所管理的對象內(nèi)存

weak pointer不會影響shared pointer指向?qū)ο蟮囊糜?jì)數(shù),當(dāng)引用計(jì)數(shù)為零的時(shí)候博肋,不管有沒有weak pointer指向?qū)ο蟮驼瑢ο蟮膬?nèi)存都會被釋放

class A;
class B;
class A{
public:
    shared_ptr<B> pb;
};
class B{
public:
    shared_ptr<A> pa;
};
void func(){
    shared_ptr<A> pa(new A());
    shared_ptr<B> pb(new B());
    pa->pb = pb;
    pb->pa = pa;
}

當(dāng)函數(shù)func執(zhí)行完畢跳出,pa匪凡、pb被釋放膊畴,pa、pb指向?qū)ο蟮囊糜?jì)數(shù)都減一變?yōu)?病游,所以A和B的具體對象并沒有被釋放唇跨,造成內(nèi)存泄漏

class A;
class B;
class A{
public:
    weak_ptr<B> pb;
};
class B{
public:
    shared_ptr<A> pa;
};
void func(){
    shared_ptr<A> pa(new A());
    shared_ptr<B> pb(new B());
    pa->pb = pb;
    pb->pa = pa;
}

當(dāng)函數(shù)體執(zhí)行完畢前,A的引用計(jì)數(shù)是2衬衬,B是1买猖,pa、pb被釋放滋尉,A和B的引用計(jì)數(shù)都減一政勃,B變?yōu)?,會被釋放兼砖,B中的pa指針被釋放,A對象的引用計(jì)數(shù)減一變?yōu)?既棺,A被釋放

16. 封裝讽挟、繼承、多態(tài)

是C++面向?qū)ο缶幊痰奶攸c(diǎn)

封裝是將數(shù)據(jù)和操作數(shù)據(jù)的方法封裝在一個(gè)類中丸冕,在類的內(nèi)部實(shí)現(xiàn)對數(shù)據(jù)的操作
將復(fù)雜的操作實(shí)現(xiàn)放在類的內(nèi)部耽梅,為外部提供接口,使得程序更容易被理解和分工
類的內(nèi)部成員有不同的權(quán)限胖烛,能防止程序中無關(guān)部分修改成員眼姐,數(shù)據(jù)更加安全

繼承是指派生類繼承基類,派生類擴(kuò)展基類的成員和方法佩番,使得代碼得到更好的復(fù)用

多態(tài)指一個(gè)函數(shù)存在多種實(shí)現(xiàn)方法
有兩種众旗,編譯時(shí)多態(tài)和運(yùn)行時(shí)多態(tài)
編譯時(shí)多態(tài)指的是重載,就是一個(gè)類中的函數(shù)有相同的函數(shù)名趟畏,但是參數(shù)列表不同
運(yùn)行時(shí)多態(tài)指的是重寫贡歧,通過虛函數(shù)實(shí)現(xiàn),在基類和派生類中有函數(shù)名稱和參數(shù)列表都相同的函數(shù),但是函數(shù)名前有virtual的關(guān)鍵字

17. 四種類型轉(zhuǎn)換

static cast:用于風(fēng)險(xiǎn)小的類型轉(zhuǎn)換利朵,比如浮點(diǎn)數(shù)和整數(shù)的轉(zhuǎn)換律想,派生類指針到基類指針的轉(zhuǎn)換

const cast:用于去除常量屬性

reinterpret cast:用于不同類型的指針之間的轉(zhuǎn)換,以及能容納得下指針的整數(shù)和指針之間的轉(zhuǎn)換

dynamic cast:用于含有虛函數(shù)的類的向基類或向派生類的轉(zhuǎn)換

18. 指針和引用的區(qū)別

指針存儲一個(gè)內(nèi)存地址绍弟,引用相當(dāng)于變量的別名
系統(tǒng)會為指針分配內(nèi)存技即,不會給引用分配內(nèi)存
指針可以修改所存的地址,引用一和變量綁定就無法再綁定其他變量
引用必須初始化

19. 指針和數(shù)組的區(qū)別

指針保存地址樟遣,數(shù)組保存相同數(shù)據(jù)類型的數(shù)據(jù)
指針通過地址間接訪問數(shù)據(jù)而叼,數(shù)組直接訪問數(shù)據(jù)
指針需要顯式分配和釋放內(nèi)存,數(shù)組自動分配和釋放
指針動態(tài)分配內(nèi)存大小年碘,數(shù)組在定義時(shí)就確定大小

20. 野指針是什么

指向非法內(nèi)存地址的指針
非法內(nèi)存:未分配的區(qū)域

21. 為什么不默認(rèn)析構(gòu)函數(shù)為虛函數(shù)

因?yàn)楹刑摵瘮?shù)的類需要虛函數(shù)表澈歉,其對象需要虛函數(shù)指針,將不含虛函數(shù)的類的析構(gòu)函數(shù)聲明為虛函數(shù)需要額外的空間開銷

22. 重載和重寫的區(qū)別

重載:同一個(gè)類中屿衅,相同函數(shù)名的函數(shù)埃难,參數(shù)列表不相同,在調(diào)用的時(shí)候根據(jù)參數(shù)列表選擇調(diào)用函數(shù)

重寫:基類和派生類中有函數(shù)名稱和參數(shù)列表都相同的函數(shù)涤久,函數(shù)聲明為virtual涡尘,在運(yùn)行的時(shí)候,根據(jù)具體的對象類型調(diào)用函數(shù)

23. 虛函數(shù)如何實(shí)現(xiàn)

通過虛函數(shù)表和虛函數(shù)指針來實(shí)現(xiàn)
每個(gè)類都有一個(gè)虛函數(shù)表响迂,表中存放虛函數(shù)的入口地址
每個(gè)對象有一個(gè)虛函數(shù)指針考抄,指向虛函數(shù)表
派生類會繼承基類的虛函數(shù)表,當(dāng)派生類重寫了基類的方法時(shí)蔗彤,派生類的虛函數(shù)表中相應(yīng)的函數(shù)的入口地址會更改

24. 隱式類型轉(zhuǎn)換

一種是用低精度變量給高精度變量賦值
一種是在含有單參數(shù)的構(gòu)造函數(shù)的類川梅,用相應(yīng)的單參數(shù)給類的對象賦值

25. 函數(shù)指針

指向函數(shù)入口地址的指針
可以用來調(diào)用函數(shù)或者作為函數(shù)的參數(shù)

26. struct和class的區(qū)別

默認(rèn)訪問權(quán)限不同,struct是public然遏,class是private
class可以用于聲明模板贫途,struct不可以

27. 內(nèi)存泄漏和場景

內(nèi)存泄漏指的是不再使用的內(nèi)存沒被釋放

常見的發(fā)生場景
new分配后沒有delete
沒有把基類的析構(gòu)函數(shù)聲明為虛函數(shù),一個(gè)基類指針指向派生類對象待侵,delete基類指針時(shí)沒有準(zhǔn)確的釋放派生類對象擴(kuò)充的部分

28. inline函數(shù)和宏定義

inline在編譯時(shí)將代碼嵌入相應(yīng)位置丢早,宏定義預(yù)處理階段簡單替換
inline函數(shù)有語法詞法分析,可以查出語法詞法錯(cuò)誤秧倾,宏定義沒有
inline函數(shù)不會有歧義怨酝,宏定義可能產(chǎn)生歧義

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市那先,隨后出現(xiàn)的幾起案子农猬,更是在濱河造成了極大的恐慌,老刑警劉巖售淡,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盛险,死亡現(xiàn)場離奇詭異瞄摊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)苦掘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門换帜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鹤啡,你說我怎么就攤上這事惯驼。” “怎么了递瑰?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵祟牲,是天一觀的道長。 經(jīng)常有香客問我抖部,道長说贝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任慎颗,我火速辦了婚禮乡恕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘俯萎。我一直安慰自己傲宜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布夫啊。 她就那樣靜靜地躺著函卒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撇眯。 梳的紋絲不亂的頭發(fā)上报嵌,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機(jī)與錄音熊榛,去河邊找鬼沪蓬。 笑死,一個(gè)胖子當(dāng)著我的面吹牛来候,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逸雹,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼营搅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了梆砸?” 一聲冷哼從身側(cè)響起转质,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎帖世,沒想到半個(gè)月后休蟹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沸枯,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年赂弓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了绑榴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盈魁,死狀恐怖翔怎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情杨耙,我是刑警寧澤赤套,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站剔氏,受9級特大地震影響堪遂,放射性物質(zhì)發(fā)生泄漏溶褪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一吹菱、第九天 我趴在偏房一處隱蔽的房頂上張望彭则。 院中可真熱鬧鳍刷,春花似錦输瓜、人聲如沸尤揣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蠕嫁。三九已至锨天,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绍绘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工酌媒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喇辽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓菩咨,卻偏偏與公主長得像抽米,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子标捺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344