C++常見面試問題彙總

參考:

https://www.jianshu.com/p/9aae0e5dc21a 

https://www.cnblogs.com/hit-ycy/p/11208052.html

  • 指針和引用的區別

  1. 指針有自己的一塊空間,而引用只是一個別名。
  2. 不存在空引用。引用必須連接到一塊合法的內存。
  3. 一旦引用被初始化爲一個對象,就不能被指向到另一個對象。指針可以在任何時候指向到另一個對象。
  4. 引用必須在創建時被初始化。指針可以在任何時間被初始化。
  • 堆和棧的區別

  1. C++ 程序中的內存分爲兩個部分:
  • 棧:在函數內部聲明的所有變量都將佔用棧內存。
  • 堆:這是程序中未使用的內存,在程序運行時可用於動態分配內存。
  • new和delete是如何實現的,new 與 malloc的異同處

new/delete是C++的關鍵字,而malloc/free是C語言的庫函數,後者使用必須指明申請內存空間的大小,對於類類型的對象,後者不會調用構造函數和析構函數

  • C和C++的區別

設計思想上:

C++是面向對象的語言,而C是面向過程的結構化編程語言

語法上:

C++具有封裝、繼承和多態三種特性

C++相比C,增加多許多類型安全的功能,比如強制類型轉換

C++支持範式編程,比如模板類、函數模板等

  • C++、Java的聯繫與區別,包括語言特性、垃圾回收、應用場景等(java的垃圾回收機制)

語言特性的話:c++ 有指針多重繼承強制類型轉換

Java 有垃圾回收機制能夠自動釋放掉申請的內存,而C++是以能夠操作內存著稱,但是很容易帶來一些錯誤

Java是完全面向對象的語言,所有函數和變量部必須是類的一部分。除了基本數據類型之外,其餘的都作爲類對象,包括數組。對象將數據和方法結合起來,把它們封裝在類中,這樣每個對象都可實現自己的特點和行爲。而c++允許將函數和變量定義爲全局的。此外,Java中取消了c/c++中的結構和聯合,消除了不必要的麻煩。 

應用場景:c++用於底層和中間件,java用於高層

  • Struct和class的區別

在C++中,可以用struct和class定義類,都可以繼承。

區別在於:struct的默認繼承權限和默認訪問權限是public,而class的默認繼承權限和默認訪問權限是private。

另外,class還可以定義模板類形參,比如template <class T, int i>。

  • define 和const的區別(編譯階段、安全性、內存佔用等)

區別
(1)就起作用的階段而言: #define是在編譯的預處理階段起作用,而const是在編譯、運行的時候起作用。
(2)就起作用的方式而言: #define只是簡單的字符串替換,沒有類型檢查。而const有對應的數據類型,是要進行判斷的,可以避免一些低級的錯誤。 
(3)就存儲方式而言:#define只是進行展開,有多少地方使用,就替換多少次,它定義的宏常量在內存中有若干個備份;const定義的只讀變量在程序運行過程中只有一份備份。
(4)從代碼調試的方便程度而言: const常量可以進行調試的,define是不能進行調試的,因爲在預編譯階段就已經替換掉了。

const優點
(1)const常量有數據類型,而宏常量沒有數據類型。編譯器可以對前者進行類型安全檢查。而對後者只進行字符替換,沒有類型安全檢查,並且在字符替換可能會產生意料不到的錯誤。
(2)有些集成化的調試工具可以對const常量進行調試,但是不能對宏常量進行調試。
(3)const可節省空間,避免不必要的內存分配,提高效率

  • 在C++中const和static的用法(定義,用途)
  • const和static在類中使用的注意事項(定義、初始化和使用)

static成員不屬於任何對象,而是被他們共享。

靜態數據成員應該在類的外部定義。

因爲沒有this指針,static成員函數不能用const修飾,也不能訪問非靜態成員。

  • C++中的const類成員函數(用法和意義),以及和非const成員函數的區別
  • C++的頂層const和底層const
  • C++中的重載和重寫的區別

  • 重載:兩個函數名相同,但是參數列表不同(個數,類型),返回值類型沒有要求,在同一作用域中
    重寫:子類繼承了父類,父類中的函數是虛函數,在子類中重新定義了這個虛函數,這種情況是重寫

  • final和override關鍵字

final限定某個類不能被繼承或某個虛函數不能被重寫

override關鍵字保證了派生類中聲明重寫的函數與基類虛函數有相同的簽名,可避免一些拼寫錯誤,如加了此關鍵字但基類中並不存在相同的函數就會報錯,也可以防止把本來想重寫的虛函數聲明成了重載。同時在閱讀代碼時如果看到函數聲明後加了此關鍵字就能立馬知道此函數是重寫了基類虛函數。保證重寫虛函數的正確性的同時也提高了代碼可讀性。

  • 拷貝初始化和直接初始化,初始化和賦值的區別

當用於類類型對象時,初始化的複製形式和直接形式有所不同:直接初始化直接調用與實參匹配的構造函數,複製初始化總是調用複製構造函數。複製初始化首先使用指定構造函數創建一個臨時對象,然後用複製構造函數將那個臨時對象複製到正在創建的對象

  • extern "C"的用法

C++調用C函數需要extern C,因爲C語言沒有函數重載

  • 模板函數和模板類的特例化
  • C++的STL源碼(這個系列也很重要,建議侯捷老師的STL源碼剖析書籍與視頻),其中包括內存池機制,各種容器的底層實現機制,算法的實現原理等)
  • STL源碼中的hashtable的實現
  • STL中unordered_map和map的區別和應用場景
  • STL中vector的實現
  • STL容器的幾種迭代器以及對應的容器(輸入迭代器,輸出迭代器,前向迭代器,雙向迭代器,隨機訪問迭代器)

順序容器:vector,deque是隨機訪問迭代器;list是雙向迭代器

容器適配器:stack,queue,priority_queue沒有迭代器

關聯容器:set,map,multiset,multimap是雙向迭代器

unordered_set,unordered_map,unordered_multiset,unordered_multimap是前向迭代器

  • STL中的traits技法

type_traits

iterator_traits

char traits

allocator_traits

pointer_traits

array_traits

  • vector使用的注意點及其原因,頻繁對vector調用push_back()對性能的影響和原因。
  • C++內存管理,內存池技術(熱門問題),與csapp中幾種內存分配方式對比學習加深理解

c++的內存管理延續c語言的內存管理,但是也增加了其他的,例如智能指針,除了常見的堆棧的內存管理之外,c++支持智能指針,智能指針的對象進行賦值拷貝等操作的時候,每個智能指針都有一個關聯的計數器,該計數器記錄共享該對象的指針個數,當最後一個指針被銷燬的時候,計數器爲0,會自動調用析構函數來銷燬函數。

  • 介紹面向對象的三大特性,並且舉例說明每一個

繼承,多態,封裝。

繼承:本質是代碼複製。

多態:多態和虛函數

封裝:將數據和和對操作封裝到放在一起。

  • C++多態的實現
  • C++虛函數相關(虛函數表,虛函數指針),虛函數的實現原理(包括單一繼承,多重繼承等)(拓展問題:爲什麼基類指針指向派生類對象時可以調用派生類成員函數,基類的虛函數存放在內存的什麼區,虛函數表指針vptr的初始化時間)
  • C++中類的數據成員和成員函數內存分佈情況
  • this指針

每個對象都有一個特殊的指針 this,它指向對象本身。

  • 析構函數一般寫成虛函數的原因

將可能會被繼承的父類的析構函數設置爲虛函數,可以保證當我們new一個子類,然後使用基類指針指向該子類對象,釋放基類指針時可以釋放掉子類的空間,防止內存泄漏

  • 構造函數、拷貝構造函數和賦值操作符的區別

構造函數:對象不存在,沒用別的對象初始化

拷貝構造函數:對象不存在,用別的對象初始化

賦值運算符:對象存在,用別的對象給它賦值

  • 構造函數聲明爲explicit
  • 構造函數爲什麼一般不定義爲虛函數
  • 構造函數的幾種關鍵字(default delete 0)

= default:將拷貝控制成員定義爲=default顯式要求編譯器生成合成的版本

= delete:將拷貝構造函數和拷貝賦值運算符定義刪除的函數,阻止拷貝(析構函數不能是刪除的函數 C++Primer P450)

= 0:將虛函數定義爲純虛函數(純虛函數無需定義,= 0只能出現在類內部虛函數的聲明語句處;當然,也可以爲純虛函數提供定義,不過函數體必須定義在類的外部)

  • 構造函數或者析構函數中調用虛函數會怎樣

1. 從語法上講,調用完全沒有問題。
2. 但是從效果上看,往往不能達到需要的目的。
Effective 的解釋是:
派生類對象構造期間進入基類的構造函數時,對象類型變成了基類類型,而不是派生類類型。
同樣,進入基類析構函數時,對象也是基類類型。

  • 純虛函數

純虛函數的格式   virtual  f()=0;

代表我不實現,留給子類去實現,帶有純虛函數的類也叫抽象類,不能夠實例對象出來,子類必須實現,主要解決的是多態問題,面向對象的思想

動物基類不能實現,老虎,獅子等派生類可以給出對象,所以嘛出現了純虛函數抽象類這個東西

  • 靜態類型和動態類型,靜態綁定和動態綁定的介紹
  • 引用是否能實現動態綁定,爲什麼引用可以實現
  • 深拷貝和淺拷貝的區別(舉例說明深拷貝的安全性)

在有指針成員的情況下,淺拷貝只是將指針指向已存在的內存。即兩個對象的指針成員指向的是同一內存區域。

深拷貝的做法是申請一個內存複製一份,並將新對象指針指向備份區。

安全性:淺拷貝如果修改了指針指向的內容,將對兩個對象都有影響。

  • 對象複用的瞭解,零拷貝的瞭解

對象池:對象池通過對象複用的方式來避免重複創建對象,它會事先創建一定數量的對象放到池中,當用戶需要創建對象的時候,直接從對象池中獲取即可,用完對象之後再放回到對象池中,以便複用。

適用性:類的實例可重用。類的實例化過程開銷較大。類的實例化的頻率較高。

零拷貝:emplace_back

  • 介紹C++所有的構造函數

1,普通構造函數,就是普通那樣創建

2,拷貝構造函數:利用現有對象給其他對象創建     函數傳參     函數返回值 都會調用拷貝構造

3,轉換構造函數:就是隻有一個參數,可以有默認參數,它會你賦值一個值的時候直接轉換成一個對象

  • 什麼情況下會調用拷貝構造函數(三種情況)

(1)用類的一個對象去初始化另一個對象時

(2)當函數的形參是類的對象時(也就是值傳遞時),如果是引用傳遞則不會調用

(3)當函數的返回值是類的對象或引用時

  • 結構體內存對齊方式和爲什麼要進行內存對齊?

保證計算機可以一次讀出

結構體不像數組,結構體中可以存放不同類型的數據,它的大小也不是簡單的各個數據成員大小之和,限於讀取內存的要求,而是每個成員在內存中的存儲都要按照一定偏移量來存儲,根據類型的不同,每個成員都要按照一定的對齊數進行對齊存儲,最後整個結構體的大小也要按照一定的對齊數進行對齊。

同樣的結構體,裏面的數據排放順序不一樣,最後佔用的內存也不一樣大

  • 內存泄露的定義,如何檢測與避免?

內存泄漏通常是由於調用了malloc/new等內存申請的操作,但是缺少了對應的free/delete。爲了判斷內存是否泄露,我們一方面可以使用linux環境下的內存泄漏檢查工具Valgrind,另一方面我們在寫代碼時可以添加內存申請和釋放的統計功能,統計當前申請和釋放的內存是否一致,以此來判斷內存是否泄露。

  • 手寫智能指針的實現(shared_ptr和weak_ptr實現的區別)

智能指針主要用於管理在上分配的內存,它將普通的指針封裝爲一個棧對象。當棧對象的生存週期結束後,會在析構函數中釋放掉申請的內存,從而防止內存泄漏。C++ 11中最常用的智能指針類型爲shared_ptr,它採用引用計數的方法,記錄當前內存資源被多少個智能指針引用。該引用計數的內存在堆上分配。當新增一個時引用計數加1,當過期時引用計數減一。只有引用計數爲0時,智能指針纔會自動釋放引用的內存資源。對shared_ptr進行初始化時不能將一個普通指針直接賦值給智能指針,因爲一個是指針,一個是類。可以通過make_shared函數或者通過構造函數傳入普通指針。並可以通過get函數獲得普通指針。

  • 智能指針的循環引用
  • 遇到coredump要怎麼調試
  • 內存檢查工具的瞭解
  • 模板的用法與適用場景

模板是C++泛型編程的基礎。

使用:template  //關鍵字+<模板參數列表>

應用場景:除了參數類型不一樣外,其他的內容全部一樣(函數體),用模板,而不是每一個類型都寫一個函數。

特化:模板的一個獨立的定義,其中一個或多個參數被指定爲特定的類型。通用模板不能適應所有情況。(特殊情況特殊處理)

  • 成員初始化列表的概念,爲什麼用成員初始化列表會快一些(性能優勢)?
  • 用過C++ 11嗎,知道C++ 11哪些新特性?
  • C++的調用慣例(簡單一點C++函數調用的壓棧過程)
  • C++的四種強制轉換

  1. static_cast  可以實現C++中內置基本數據類型之間的相互轉換。
  2. dynamic_cast
  3. const_cast 用於將const變量轉爲非const
  4.  reinterpret_cast
  • C++中將臨時變量作爲返回值的時候的處理過程(棧上的內存分配、拷貝過程)
  • C++的異常處理
  • volatile關鍵字
  • 優化程序的幾種方法
  • public,protected和private訪問權限和繼承
  • decltype()和auto
  • inline和宏定義的區別
  • C++和C的類型安全
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章