一道非常经典C++面试题|大厂面试
問題1:小伙伴問我,這個unique_ptr出了作用域為什么沒調它的析構函數呢? ?
問題2:第一個運行結果是什么?為什么?
我把問題拋到群里討論,讓大家一起思考,大家可以先思考一下:
C++背景知識
C++程序的內存格局通常分為四個區:
全局數據區(data area)
代碼區(code area)
棧區(stack area)
堆區(heap area)(即自由存儲區)
全局數據區存放全局變量,靜態數據和常量;所有類成員函數和非成員函數代碼存放在代碼區;為運行函數而分配的局部變量、函數參數、返回數據、返回地址等存放在棧區;余下的空間都被稱為堆區。根據這個解釋,我們可以得知在類的定義時,類成員函數是被放在代碼區,而類的靜態成員變量在類定義時就已經在全局數據區分配了內存,因而它是屬于類的。對于非靜態成員變量,我們是在類的實例化過程中(構造對象)才在棧區或者堆區為其分配內存,是為每個對象生成一個拷貝,所以它是屬于對象的。
深入學習:
C++內存管理全景指南
C++的最后一道坎|百萬年薪的程序員
、
用圖表示看起來更清楚:
參考答案
第一個問題答案:
unique_ptr本身也是一個類, frame也是對象(只是指針指的是空對象),這里應該是調用unique_ptr析構函數,在~unique_ptr析構函數中,會去調用對象的析構函數,如下圖(gcc 11 unique_ptr 源碼 ),但如果對象為空,就不會去調用。
不要震驚,我們來查看匯編結果,從匯編代碼可以看到確實調用了default_delete函數(unique_ptr的默認析構函數):
查看標準說明:
https://en.cppreference.com/w/cpp/memory/unique_ptr
gcc 11 unique_ptr的源碼,通過查看gcc的源碼,確實證明我們上面的結論,如果對象為空,就不會去調用對象的析構函數:
第二個問題答案:
可以打印:frame,為什么呢?因為這里成員函數在代碼區且沒有訪問對象成員,這樣函數調用就不需要訪問this指針(這里記住了,對象成員是通過this指針來訪問的),所以不需要對象也可以訪問成員函數,如果成員函數未使用任何成員變量的話,不管是不是static的,都能正常工作。
我們可以測試一下,如果有對象成員的情況,就會導致程序異常退出,如下:
我們來升級一下問題:
程序運行結果是什么,為什么? 大家可以先思考一下。
問題參考答案:
輸出“printA”后,程序崩潰。為什么呢?printA是成員函數,存放在代碼段(.text),所以沒有實例化類的時候仍然可以調用。printB是虛函數,關系到虛函數表和虛函數指針,虛函數指針存放在實例化的對象中,所以,未實例化對象時,不存在虛函數指針,所以調用虛函數會報錯。一般找虛函數指針都是通過this指針地址+偏移來計算的,this本身是空, 算出來虛擬函數指針肯定有問題,只要訪問就會掛。
一張圖搞懂虛函數表原理
https://blog.csdn.net/u011391093/article/details/45249325
我們來看一下匯編代碼:
單步調試,程序確實會core在26行匯編:
最后總結
C++核心知識
這道經典的面試題,看起來很簡單,但卻考察C++最核心的知識,比如C++的內存管理(內存布局),智能指針原理,析構原理,虛函數原理等核心知識。
關于匯編
為什么要通過看匯編代碼來分析,那是因為匯編代碼能夠查看C++代碼到底都做了些什么操作,這樣可以找到更多線索,就像群里小伙伴說的:匯編之下,了無秘密。
大家不要害怕匯編,當你搞多了, 自然就不害怕了。
匯編其實很簡單,就是一些常見指令, 然后記住一些固定訪問模式,還有常見的場景。比如函數入參,函數調用,字符串copy ,條件判斷,指針讀取, 循環等,慢慢練,孰能生巧。
推薦匯編學習視頻,適合入門:
https://www.bilibili.com/video/BV1Pb411L73i?p=6
https://www.bilibili.com/video/BV1mt411R7Xv
文中匯編生成網站:Compiler Explorer
https://godbolt.org/,可以支持各種編譯器:
one more thing
這點非常重要,當提出這個問題后,群里一些小伙伴,就憑經驗猜想,給出一些答案,但有個小伙伴給出答案后,會同步去做代碼編譯驗證,去查看反匯編,去一步一步調試,去確認是不是符合自己的猜想。
最后祝大家面無不勝,基礎越來越扎實。
我每周都會提問幾道非常經典的面試題,通過參與這些經典的面試題分析驗證,我們可以徹底理解大廠面試的核心知識,需要深入交流學習同學,可以加入極客星球,和大家一起快速成長:
大廠求職核心原理1v1指導(職位,簡歷,面試,策略等一條龍優化)
技術問題分析解答(有專屬VIP群)
?加入極客星球,然后加我微信,進群一起學習。
大廠技術路線
后臺開發進階
開源項目學習
直播分享(已經分享了7期,加入星球可以看回放)
技術視野
按需提供經典資料,節約你
實戰技能分享
等,極客星球希望成為最有技術價值星球,盡最大努力為星球的同學提供面試,跳槽,技術成長幫助!詳情查看點擊->極客星球
- END -
看完一鍵三連在看,轉發,點贊
是對文章最大的贊賞,極客重生感謝你
推薦閱讀
定個目標|建立自己的技術知識體系
大廠后臺開發基本功修煉路線和經典資料
個人學習方法分享
你好,這里是極客重生,我是阿榮,大家都叫我榮哥,從華為->外企->到互聯網大廠,目前是大廠資深工程師,多次獲得五星員工,多年職場經驗,技術扎實,專業后端開發和后臺架構設計,熱愛底層技術,豐富的實戰經驗,分享技術的本質原理,希望幫助更多人蛻變重生,拿BAT大廠offer,培養高級工程師能力,成為技術專家,實現高薪夢想,期待你的關注!點擊藍字查看我的成長之路。
校招/社招/簡歷/面試技巧/大廠技術棧分析/后端開發進階/優秀開源項目/直播分享/技術視野/實戰高手等,?極客星球希望成為最有技術價值星球,盡最大努力為星球的同學提供面試,跳槽,技術成長幫助!詳情查看->極客星球
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 求點贊,在看,分享三連
總結
以上是生活随笔為你收集整理的一道非常经典C++面试题|大厂面试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一致性 Hash 算法原理总结
- 下一篇: C++Template 模版的本质