C++面試彙總

1、CPP內存管理

參考回答:https://www.cnblogs.com/findumars/p/5929831.html?utm_source=itdadao&utm_medium=referral
參考回答:https://blog.csdn.net/hanoi_ahoj/article/details/88660494

類中的靜態成員:靜態成員變量只能在類中聲名,不能在類中定義或者初始化,定義是爲變量分配空間,而初始化是爲變量賦值
詳解參考博客:https://www.jianshu.com/p/feaf81b88f85

參考博客(C++空間配置代碼分析):https://blog.csdn.net/haluoluo211/article/details/80560066
參考博客(C++空間配置代碼分析):https://blog.csdn.net/haluoluo211/article/details/80573204
參考博客(C++vector容器實現分析):https://blog.csdn.net/haluoluo211/article/details/80635782
C++內存管理參考博客:https://www.cnblogs.com/findumars/p/5929831.html?utm_source=itdadao&utm_medium=referral

2、new/delete和malloc/free區別

參考博客:https://www.cnblogs.com/findumars/p/5929831.html?utm_source=itdadao&utm_medium=referral

3、C++多態,靜態多態和動態多態都有什麼(靜態綁定、動態綁定)

C++的多態性用一句話概括就是:在基類的函數前加上virtual關鍵字,在派生類中重寫該函數,運行時將會根據對象的實際類型來調用相應的函數。如果對象類型是派生類,就調用派生類的函數;如果對象類型是基類,就調用基類的函數
1:用virtual關鍵字申明的函數叫做虛函數,虛函數肯定是類的成員函數
2:存在虛函數的類都有一個一維的虛函數表叫做虛表,類的對象有一個指向虛表開始的虛指針。虛表是和類對應的,虛表指針是和對象對應的
3:多態性是一個接口多種實現,是面向對象的核心,分爲類的多態性和函數的多態性
4:多態用虛函數來實現,結合動態綁定.
5:純虛函數是虛函數再加上 = 0
6:抽象類是指包括至少一個純虛函數的類
純虛函數:virtual void fun()=0;即抽象類!必須在子類實現這個函數,即先有名稱,沒有內容,在派生類實現內容

靜態多態就是在系統編譯期間就可以確定程序執行到這裏將要執行哪個函數,比如函數的重載。
動態多態則是利用虛函數實現了運行時的多態,也就是說在系統編譯的時候並不知道程序將要調用哪一個函數,只有在運行到這裏的時候才能確定接下來會跳轉到哪一個函數的棧幀

注意:C語言不支持重載,但支持變長參數:
多態有類的多態和函數的多態,函數的多態是指一個函數被定義成不同參數的函數,當調用函數時,根據不同的參數調用不同的函數

那些函數不能定義爲虛函數?
經檢驗下面的幾個函數都不能定義爲虛函數:
1)友元函數,它不是類的成員函數
2)全局函數
3)靜態成員函數,它沒有this指針
3)構造函數,拷貝構造函數,以及賦值運算符重載(可以但是一般不建議作爲虛函數)

參考博客:https://www.cnblogs.com/cxq0017/p/6074247.html
參考博客:https://blog.csdn.net/qq_39412582/article/details/81628254

4、類的虛函數的作用;B類繼承A類,AB類中均定義S函數;內部機制(虛函數表)**

參照第3問
**基類析構函數定義爲虛函數的原因:**基類指針可能指向派生類,當delete的時候,如果不定爲虛函數,系統會直接調用基類的析構函數,這個時候派生類就有一部分沒有被釋放,就會造成可怕的內存泄漏問題
若定義爲虛函數,那麼就會先調用派生類的析構函數然後派生類的析構函數會自動調用基類的析構函數,這個結果滿足我們的本意

所以!在繼承的時候,儘量把基類的析構函數定義爲虛函數,這樣繼承下去的派生類的析構函數也會被變成虛函數構成多態

參考博客(C++多態):https://blog.csdn.net/skySongkran/article/details/82012698
參考博客(C++多態):https://blog.csdn.net/qq_39412582/article/details/81628254
參考博客(C++多態):https://blog.csdn.net/weixin_42678507/article/details/89414998

5、四種強制類型轉換:靜態轉換、常量轉換、重解釋轉換、動態轉換**
  • static_cast轉換:可用於基本數據類型的轉換,也可用於基類和派生間的轉換(父類、子類)
    在進行類間轉換時:
    上行轉換(派生類---->基類)是安全的
    下行轉換(基類---->派生類)由於沒有動態類型檢查,所以是不安全的
    隱式轉換都建議使用static_cast進行顯示轉換
  • dynamic_cast轉換:只有在派生類之間轉換時才使用dynamic_cast,type-id必須是類指針,類引用或者void*
    基類必須要有虛函數,因爲dynamic_cast是運行時類型檢查,需要運行時類型信息,而這個信息是存儲在類的虛函數表中,只有一個類定義了虛函數,纔會有虛函數表
    對於下行轉換,dynamic_cast是安全的(當類型不一致時,轉換過來的是空指針),而static_cast是不安全的(當類型不一致時,轉換過來的是錯誤意義的指針,可能造成踩內存,非法訪問等各種問題)
  • const_cast轉換:const_castexpression
    使用場景:
      a、常量指針轉換爲非常量指針,並且仍然指向原來的對象
      b、常量引用被轉換爲非常量引用,並且仍然指向原來的對象
    使用特點:
      a、cosnt_cast是四種類型轉換符中唯一可以對常量進行操作的轉換符
      b、去除常量性是一個危險的動作,儘量避免使用。一個特定的場景是:類通過const提供重載時,一般都是非常量函數調用const_cast將參數轉換爲常量,然後調用常量函數,然後得到結果再調用const_cast 去除常量性
  • reinterpret_cast轉換:reinterpret_castexpression
    使用場景:不到萬不得已,不用使用這個轉換符,高危操作
    使用特點:  
      a、reinterpret_cast是從底層對數據進行重新解釋,依賴具體的平臺,可移植性差
      b、reinterpret_cast可以將整型轉換爲指針,也可以把指針轉換爲數組
      c、reinterpret_cast可以在指針和引用裏進行肆無忌憚的轉換

回答參考:https://www.cnblogs.com/cauchy007/p/4968707.html

6、inline內聯函數

內聯函數:

  • 內聯函數在編譯時進行類型檢查和自動類型轉換
  • 內聯可以調試
  • 可訪問成員變量

宏定義:只在預編譯的時候進行替換

參考博客:https://www.jianshu.com/p/89d2c1d8b202
參考博客(內聯函數和宏定義):https://www.cnblogs.com/xuewangkai/p/11151246.html

7、代碼到生成可執行文件的流程

C++的編譯過程包括
step1 預編譯
step2 彙編
step3 編譯
step4 鏈接

預編譯:主要展開頭文件、宏定義等。彙編:把已經預編譯的文件編譯成彙編代碼,整個過程包含語法、詞法的分析,和一些優化操作
編譯:將彙編代碼變成目標代碼,即生成二進制文件(.obj)
鏈接:將單個編譯後的文件鏈接成一個可執行文件
前面的預編譯、彙編、編譯都是針對單個文件,以一個文件爲一個編譯單元,而鏈接則是將所有關聯到的編譯後的單元文件和應用到的庫文件,進行一次鏈接處理,之前編譯過的文件如果有用到其他文件裏面定義到的函數、全局變量,在這個過程中會進行解析

  1. 預編譯
    將.c 文件轉化成 .i文件
    使用的gcc命令是:gcc –E
    對應於預處理命令cpp

  2. 編譯
    將.c/.h文件轉換成.s文件
    使用的gcc命令是:gcc –S
    對應於編譯命令 cc –S

  3. 彙編
    將.s 文件轉化成 .o文件
    使用的gcc 命令是:gcc –c
    對應於彙編命令是 as

  4. 鏈接
    將.o文件轉化成可執行程序
    使用的gcc 命令是: gcc
    對應於鏈接命令是 ld

總結起來編譯過程就上面的四個過程:預編譯處理(.c) --> 編譯、優化程序(.s、.asm)--> 彙編程序(.obj、.o、.a、.ko) --> 鏈接程序(.exe、.elf、.axf等)

參考博客:https://blog.csdn.net/gongjiwei/article/details/98845482
參考博客:https://blog.csdn.net/u012662731/article/details/78520349

8、C++協變與逆變

如果類型 Car 是類型 Vehicle 的子類型(subtype,Car ≤ Vehicle,可以在任何出現 Vehicle 的地方用 Car 代替),那麼關於 Car 和 Vehicle 的複雜類型(如 std::vector 和 std::vector)之間的關係如下:

  • std::vector 是 std::vector 的子類型,所有出現 std::vector 的地方都可以用 std::vector 代替,即代替方向一致,則稱之爲協變(covariance)
  • std::vector 是 std::vector 的子類型,所有出現 std::vector 的地方都可以用 std::vector 代替,即代替方向相反,則稱之爲逆變(cotravariance)
  • std::vector 和 std::vector 之間沒有關係,則稱之爲不變(invariance)

參考博客:https://www.jianshu.com/p/db76a8b08694

9、什麼是智能指針? 智能指針的原理什麼? 使用智能指針的目的是什麼? 使用智能指針一定可以防止內存泄露嗎? (什麼情況下使用智能指針仍然會導致泄露)**

參考博客:https://www.jianshu.com/p/bf8de014e5c2
參考博客:https://www.cnblogs.com/wxquare/p/4759020.html
參考博客:https://blog.csdn.net/flowing_wind/article/details/81301001

10、瞭解的C++11新特性(說的智能指針)
11、如何實現一個只能在堆上建立實例的類**

參考博客:https://blog.csdn.net/c_base_jin/article/details/86501333
參考博客:https://www.cnblogs.com/luxiaoxun/archive/2012/08/03/2621827.html

12、設計模式瞭解哪些

單例模式、工廠模式、抽象工廠模式、備忘錄模式、觀察者模式、策略模式

13、什麼是死鎖?

參考博客:https://blog.csdn.net/hd12370/article/details/82814348

14、TCP UDP區別

參考博客:https://blog.csdn.net/gongjiwei/article/details/98896267

17、進程和線程,說下多線程共享的資源

17、C++裏面的const關鍵字,能修飾volatile嗎?

18、C++裏面的內存泄露?

**內存泄漏的定義:**一般我們常說的內存泄漏是指堆內存的泄漏。堆內存是指程序從堆中分配的,大小任意的(內存塊的大小可以在程序運行期決定),使用完後必須顯示釋放的內存。應用程序一般使用malloc,realloc,new等函數從堆中分配到一塊內存,使用完後,程序必須負責相應的調用free或delete釋放該內存塊,否則,這塊內存就不能被再次使用,我們就說這塊內存泄漏了

**檢測內存泄漏:**檢測內存泄漏的關鍵是要能截獲住對分配內存和釋放內存的函數的調用。截獲住這兩個函數,我們就能跟蹤每一塊內存的生命週期,比如,每當成功的分配一塊內存後,就把它的指針加入一個全局的list中;每當釋放一塊內存,再把它的指針從list中刪除。這樣,當程序結束的時候,list中剩餘的指針就是指向那些沒有被釋放的內存。這裏只是簡單的描述了檢測內存泄漏的基本原理,詳細的算法可以參見Steve Maguire的<>

參考博客:https://www.cnblogs.com/findumars/p/5929831.html?utm_source=itdadao&utm_medium=referral

19、C的malloc和C++ new的區別?

20、父類指針指向子類對象,用該指針調用子類的方法? 不會(dynamic_cast)

21、解釋一下堆棧**

參考博客:https://www.cnblogs.com/findumars/p/5929831.html?utm_source=itdadao&utm_medium=referral

22、epoll和select的區別

23、b 樹和b+樹的區別

24、scala和Cpp的區別

25、線程池的設計與相關問題

26、引用和指針區別 有常量引用嗎?指針常量和常量指針

**大對象用const引用傳遞代替按值進行函數參數傳遞:**因爲值傳遞會生成很多臨時對象,進行內存拷貝,而且如果類中使用動態內存分配,還容易引發內存泄漏,因此,使用引用傳遞可以減小臨時對象帶來的開銷,同時避免引發內存泄漏

27、一致性哈希

28、析構函數可以拋出異常嗎
不可以,析構函數拋出異常將導致內存不能釋放

29、索引失效情況

30、數據庫的存儲過程

31、volatile關鍵字

32、如果c++ 當中判斷一個類型有沒有某個方法你有哪些方式可以做到?發散一下思維,這個問題可能比較難

33、設計一個線程安全的HashMap

34、vector的內存是怎麼管理的?底層的實現

35、STL中unique函數的實現

36、進程空間的理解,怎麼求一個進程可用棧空間的大小?

37、MySQL數據庫引擎說一下

38、表過大會有什麼影響、怎麼解決(我說了水平分表和垂直分表詳細解釋)

39、水平分表固定哈希,如果想要加表、刪表怎麼辦

40、協程和線程的區別

41、一個二叉樹上求兩個節點之間路徑長度的最大值,說出具體的思路

42、STL function有個特點,他的接口都是iterator,但是在用的時候傳入容器的iterator或者說傳入數據的指針都可以work這個背後的機理是什麼?

43、模板當中對類型操作的思考

44、現在假設有一個程序,編譯好的,編譯沒有錯誤,但是運行的時候報錯,報的錯是你正在調用一個純虛函數,請問這裏面導致這個錯誤的原因可能是什麼?根據c++內部原理推理這個問題

45、描述一下,子類構造的時候,整個構造的過程,先怎麼樣,再怎麼樣,說清楚,是先構造父類的虛表指針還是先構造父類的成員?虛表指針是什麼時候設進去的? 在構造函數當中一部分是初始化列表一部分是在花括弧裏面,你能說一下這些的順序是什麼麼?差別是什麼 和this指針的順序?初始化列表的寫法和順序有沒有什麼關係?

46、瞭解什麼rpc方式

47、c++的內存管理有了解過麼?

48、new一個對象的時候該對象在內存當中是怎麼佈局的

49、成員變量,虛函數表在哪個位置?

50、一個類可能會有父類和子類那麼這些信息在對象當中是如何排版的呢?

51、在子類的構造函數中調用虛函數,調用的是父類的實現還是子類的實現

52、虛函數指針和構造函數體那個先被構造?

53、 c++運行構造函數的時候虛函數表被構造出來了麼?

54、什麼是TCP粘包

55、什麼是平衡二叉樹

56、單鏈表如何判斷有環?環的位置在哪?

57、棧和堆的理解,知不知道棧幀

22、談一下磁盤故障預測的過程

23、談一下ceph bluestore和filestore的區別,filestore爲什麼使用日誌,以及分佈式存儲中,日誌的作用

24、內存屏障

25、談一下塊設備爲什麼叫塊設備,以及ssd和hdd在順序寫和隨機寫方面的性能差別,以及原因

26、塊設備爲什麼叫塊設備,寫塊設備時,若所寫位置的開始地址不是塊對齊,如何寫到磁盤中。(面試官說這題是加分題,我只回答出來了方法,代碼沒有寫出來,不知道有沒有加分)

27、談一下ceph底層存儲的方式,以及將simple write改爲append-only形式有何優勢

28、講講STL的容器

面試經驗:https://www.nowcoder.com/discuss/188367?type=2&order=0&pos=13&page=3

學習資料:https://www.nowcoder.com/discuss/193598?type=2&order=0&pos=2&page=2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章