《深度探索c++記憶體模型》讀書筆記 (二)
前言
c++ 編譯器會在人意想不到的地方做一些隱式操作。例如,只含有一個引數的建構函式,會被當做型別轉換運算子。而關鍵字explict就是為了阻止這一機制。
預設建構函式
c++ 編譯器會在需要的時候自動生成預設建構函式。
帶有預設建構函式的類物件成員
如果一個類沒有任何的建構函式,但是它有一個物件成員,這個物件成員有一個預設建構函式。那麼編譯器將會為這個類生成一個預設建構函式。但是這個生成的時機會是在這個類被呼叫的時候。
如果有兩個檔案中都呼叫了這個類,那麼預設建構函式將可能會被生成兩次。如何避免這種衝突呢?解決方法是把合成的建構函式內聯(inline, 一個行內函數有靜態連結 static linkage)。如果建構函式太複雜,不適合內聯,那麼就會合成一個顯式的非內聯靜態實體(explicit noinline static)。
例如:
class Foo {
public:
Foo()
};
class Bar {
Foo foo;
char *str;
};
// 編譯器將會為Bar合成預設建構函式,初始化foo成員。但是並不會初始化str成員!!!
如果一個類Foo有自己定義的建構函式(預設的,或者帶有引數的),並且這個類還有一個或者多個類成員。那麼編譯器將會保證這些類成員的建構函式在Foo的建構函式中至少被呼叫一次。這些成員的構造順序與它們在class中的宣告順序一致。
帶預設建構函式的基類
類似的,如果一個沒有建構函式的派生類繼承自一個帶有預設建構函式的基類。那麼編譯器將會為這個派生類生成預設建構函式。在這個生成的建構函式中按照宣告的順序呼叫基類的建構函式。
如果派生類有建構函式,但是沒有預設建構函式。編譯器將會為現有的建構函式中安插呼叫基類建構函式的程式碼,但是並不會生成一個新的預設建構函式。
如果這個派生類同時有類成員(這些類成員有預設建構函式)。那麼編譯器將會在基類建構函式的程式碼後面安插呼叫資料成員建構函式的程式碼。
帶有虛擬函式的類
有以下兩種情況會生成預設建構函式
- 類宣告或者繼承一個虛擬函式
- 類派生自一個繼承串鏈,其中有一個或者更多的虛基類(virtual base class)
在編譯期間,編譯器會做兩件事情:
- 生成一個虛擬函式表
- 為每一個物件新增一個額外的虛擬函式表指標。
對於類所定義的每一個建構函式,編譯器將會安插一些程式碼,為虛表指標賦初值。帶有一個虛基類的類編譯器會使一個虛基類在派生類中的位置 在執行期間所決定??
例如
class X{public: int i};
class A :public virtual X {public: int j;};
class B :public virtual X {public: double d;};
class C :public A, public B {public: int k;};
// 無法在編譯時期決定i的位置(偏移?)
void foo(const A *pa) {
pa->i = 1024;
}
int main ()
{
foo (new C);
foo (new A);
...
}
編譯器的一種可能的實現方式為:
在每一個派生類的虛基類中安插一個指標。經由引用或者指標來存取一個虛基類的功能都可以由這個指標來實現。
例如:
// 可能的轉換操作
void foo(const A *pa) {
pa->__vbcX->i = 1024;
}
總結
在編譯器合成的預設建構函式中,會為那些有預設建構函式的成員或者基類呼叫其預設建構函式。而那些其他的非靜態資料成員,例如整數,指標等都不會被初始化,需要類的設計者(就是程式設計師了)來做這些操作。
新手一般會有兩個誤解:
- 任何類如果沒有定義預設建構函式,那麼就會被合成出一個來。
- 編譯器合成的預設建構函式會明確設定類中的每一個資料成員初始值。
這兩個沒有一個是真的!!!
相關文章
- 《深度探索C++物件模型》讀書筆記C++物件模型筆記
- 深度解讀《深度探索C++物件模型》之C++物件的記憶體佈局C++物件模型記憶體
- C++記憶體模型實踐探索C++記憶體模型
- JVM讀書筆記之記憶體管理JVM筆記記憶體
- 探索Java記憶體模型Java記憶體模型
- Java記憶體模型FAQ(二) 其他語言,像C++,也有記憶體模型嗎?Java記憶體模型C++
- 讀書筆記】《PostgreSQL指南-內幕探索》-2.程式和記憶體架構筆記SQL記憶體架構
- 讀書筆記2-記憶體優化篇筆記記憶體優化
- JVM讀書筆記之java記憶體結構JVM筆記Java記憶體
- 《Effective C++》讀書筆記C++筆記
- C++讀書筆記:字串C++筆記字串
- JVM讀書筆記之垃圾收集與記憶體分配JVM筆記記憶體
- 深度解讀《深度探索C++物件模型》之C++虛擬函式實現分析(二)C++物件模型函式
- 《深入java虛擬機器》讀書筆記之Java記憶體區域Java虛擬機筆記記憶體
- 記憶體模型記憶體模型
- 讀書筆記筆記
- 聊聊 記憶體模型與記憶體序記憶體模型
- 《分散式快取》讀書筆記二分散式快取筆記
- 《夢斷程式碼》讀書筆記(二)筆記
- 深度解讀《深度探索C++物件模型》之資料成員的存取效率分析(二)C++物件模型
- c++之引用及記憶體分割槽模型C++記憶體模型
- 【書生浦語大模型實戰營學習筆記】第二課 8G 視訊記憶體玩轉書生大模型 Demo大模型筆記記憶體
- 深度探索C++物件模型電子書pdf下載C++物件模型
- Java記憶體區域和記憶體模型Java記憶體模型
- Java記憶體模型FAQ(一) 什麼是記憶體模型Java記憶體模型
- 《讀書與做人》讀書筆記筆記
- Java虛擬機器記憶體模型學習筆記Java虛擬機記憶體模型筆記
- Java記憶體模型Java記憶體模型
- Java 記憶體模型Java記憶體模型
- JVM記憶體模型JVM記憶體模型
- ffmpeg記憶體模型記憶體模型
- 《Effective Java 第二版》讀書筆記Java筆記
- webpackDemo讀書筆記Web筆記
- Vue讀書筆記Vue筆記
- 散文讀書筆記筆記
- Cucumber讀書筆記筆記
- HTTP 讀書筆記HTTP筆記
- postgres 讀書筆記筆記