C 編譯機制(vc )

2021-07-05 06:56:07 字數 1644 閱讀 5969

2023年9月10日早上10點,面試京東數字營銷業務部機器學習系統架構工程師,二面掛在了c++編譯機制上面,當然自己平時沒有了解過這方面的東西,掛了也算是理所當然。

網上這方面的資料不多,但是有一本翻譯過來的文件,

c++ under the hood

這本書裡面詳細的介紹了c++的編譯機制,有興趣的可以在這裡看中譯本

在vc++編譯器中,類在記憶體中是這樣布局的首先排列非虛繼承的基類例項(按照變數定義的順序依次分配,當然中間可能有需要記憶體對其之類的情況)

有虛基類時,為每個基類增加乙個隱藏的vbptr(virtual base class pointer),除非已經從非虛繼承的類繼承過來了。

排列派生類的新資料成員(依然按照定義的先後)

最後排列每個虛基類的例項(編譯器優化)

現在對於這樣乙個類

struct c 

;struct e

;struct f : c,e

;

其記憶體分配如下

從左往右依次每個類中變數按順序分配,現在我們要進行如下訪問。

f f;

f->c1 //直接記憶體開始到c1所佔記憶體的長度

f->e1 //開始+c的偏移量到e1所佔長度

f->f1 //c+e的偏移量和到f1所佔長度

這樣成員變數的訪問還是很迅速的。因為內嵌的基類例項位址比起派生類,要麼位址相同(f和c),要麼相差固定偏移量(f和e)。

為了保證多個類繼承乙個相同的基類,而這個類不重複的分配記憶體,那麼就有了虛繼承。

假如這樣

struct employee ;

struct manager : virtual employee ;

struct worker : virtual employee ;

struct middlemanager : manager, worker ;

這樣就需要維護乙個vbptr,其中儲存的是每個每個類訪問虛函式的偏移量,so…不管是實現開銷還是呼叫開銷都比較大,因為每次都要訪問這個vbptr。

其實前面都說了,這個儲存起來之後,沒有虛繼承的話每次只要是才開始或者乙個固定的偏移量去找,有虛繼承,不同的類訪問虛類變數的時候要根據變化的vbptr計算一次。

其實強制轉話也是一樣的,向下強制轉化可以看成是把記憶體中的前面一部分或者後面一部分忽略掉,向上強制轉化就是加一部分,其實和訪問成員變數的開銷是一樣的。

每個成員函式有乙個隱藏的變數,this指標,在後台初始化為指向成員函式所在的物件,所以在函式中成員變數的訪問就是通過後台計算this指標的偏移來進行

首先需要申明一點的是,成員函式是不用存在記憶體中的,我們知道編譯的時候分程式段和資料段,前面說的那些事存在資料段的(棧上),而成員函式之類的要儲存在程式段。

這裡的難點主要是涉及到虛函式,虛函式的訪問需要乙個調整塊之類的東西,後面在詳細看看之後再寫。

VC的預編譯機制

所謂的預編譯頭就是把乙個工程中的那一部分 預先編譯好放在乙個檔案裡 通常是以.pch為副檔名的 這個檔案就稱為預編譯標頭檔案這些預先編譯好的 可以是任何的 c c 甚至是inline的函式,但是必須是穩定的,在工程開發的過程中不會 被經常改變。如果這些 被修改,則需要重新編譯生成預編譯標頭檔案。注意...

VC編譯選項

vc編譯選項 od 禁用優化 預設值 disable optimizations default ox 最大化選項。ogityb2 gs maximum opts.ogityb1 gs og 啟用全域性優化 enable global optimization oy 啟用框架指標省略 enable ...

VC 編譯設定

使用dll,採用顯式宣告時,可以用如下三種方式新增lib a.可以到 project 選單下選擇 add to project files 然後把lib檔案加進來。b.也可以設定工程選項 到 project 選單下選擇 settings 然後選擇 link 選項卡,在其中的object librar...