快樂蝦
http://blog.csdn.net/lights_joy/
本文適用於
Xp sp3
Vs2008
歡迎轉載,但請保留作者信息
轉自:http://blog.csdn.net/lights_joy/article/details/4548382
多年前學習C++的時候就知道每個類都有一個默認的構造函數,但是爲什麼要有這樣的規則卻一直不求甚解,汗一個。剛好最近在重新學習C++的內存模型,看看它到底做了麼事?
寫一個簡單的類:
class CParentA
{
public:
CParentA() {}
public:
int parenta_a;
int parenta_b;
public:
virtual void parenta_f1() {this->parenta_a = 0x10;}
virtual void parenta_f2() {this->parenta_a = 0x20;}
public:
void parenta_f3() {this->parenta_a = 0x30;}
void parenta_f4() {this->parenta_a = 0x40;}
};
看看構造函數的彙編代碼:
CParentA() {}
00401330 55 push ebp
00401331 8B EC mov ebp,esp
00401333 51 push ecx
00401334 89 4D FC mov dword ptr [ebp-4],ecx
00401337 8B 45 FC mov eax,dword ptr [this]
0040133A C7 00 60 68 40 00 mov dword ptr [eax],offset CParentA::`vftable' (406860h)
00401340 8B 45 FC mov eax,dword ptr [this]
00401343 8B E5 mov esp,ebp
00401345 5D pop ebp
00401346 C3 ret
從這裏發現了兩行很有意思的代碼:
00401337 8B 45 FC mov eax,dword ptr [this]
0040133A C7 00 60 68 40 00 mov dword ptr [eax],offset CParentA::`vftable' (406860h)
我們知道在有vtbl的情況下,this指向的前四個字節用來存放vtbl的指針。原來在構造函數裏還有一個工作是要設置vtbl的指針。難怪C++非要在裏面插入一個構造函數。
刪除我們自己寫的構造函數,再構造一個CParentA的對象。
CParentA pa;
0040111E 8D 4D F0 lea ecx,[pa] //尋址到pa 的內存位置
00401121 E8 39 FF FF FF call CParentA::CParentA (40105Fh)
還是要調用CParentA::CParentA,看看它做了什麼:
CParentA::CParentA:
004013D0 55 push ebp
004013D1 8B EC mov ebp,esp
004013D3 51 push ecx
004013D4 89 4D FC mov dword ptr [ebp-4],ecx
004013D7 8B 45 FC mov eax,dword ptr [this]
004013DA C7 00 60 68 40 00 mov dword ptr [eax],offset CParentA::`vftable' (406860h)
004013E0 8B 45 FC mov eax,dword ptr [this]
004013E3 8B E5 mov esp,ebp
004013E5 5D pop ebp
004013E6 C3 ret
比較兩個構造函數的彙編代碼可以發現,它們並沒有什麼不同。
那麼,假如一個類沒有虛函數,也就沒有vtbl,那麼它是不是就不需要生成構造函數了呢?試試將CParentA裏面的兩個虛函數去掉:
CParentA pa;
可以發現,這行代碼果然不再生成對構造函數的調用!