OS :winxp 、平臺:i386
/*
* 以下是測試代碼
*/
/*
* class obj
*/
class obj
{
public:
int m_i;
int *m_pi;
obj(int *ptemp)
{
printf("this point to %x/n" , (unsigned int)this );
m_i = 0;
printf("address of m_i = %x/n" , (unsigned int)&m_i );
this->m_pi = ptemp;
printf("address of m_pi = %x/n" , (unsigned int)&m_pi);
}
void funcA()
{
printf("this is funcA/n");
}
void funcB()
{
printf("this is funcB/n");
}
virtual void vfunc()
{
printf("this is virtual func");
}
~obj()
{
}
};
/* main */
int main(int arg , char *argv[])
{
int n = 2 ;
obj *po = new obj(&n);
cout<<"***after construt***"<<endl;
printf("address of po = %x " , (unsigned int)po );
cout<<po->m_i<<endl;
cout<<*po->m_pi<<endl;
delete po ;
}
1.初始化過程:
我們知道類的對象初始化需要調用類的構造函數。那麼這個過程是怎麼樣的呢?我們先來看看對象的初始化過程。
(一) obj *po = new obj(&n) ;
對應彙編:
00401C23 0F BF 0D 5C 55 41 00 movsx ecx,word ptr [`main'::`2'::__LINE__Var (0041555c)]
00401C2A 83 C1 11 add ecx,11h
00401C2D 51 push ecx
00401C2E 68 20 55 41 00 push offset THIS_FILE (00415520)
00401C33 6A0C push 0Ch
00401C35 E8 80 FB FF FF call operator new (004017ba)/*1 調用operator new(new操作符)分配了sizeof(obj)大小的內存空間。*/
00401C3A 83 C4 0C add esp,0Ch
00401C3D 89 45 E0 mov dword ptr [ebp-20h],eax /*2.eax中保存了返回的內存起始地址指針,此處把起始地址指針保存在[ebp-20h]中。現在我們記住eax的值,我這裏是0x00421110,後面有用*/
00401C40 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0
00401C47 83 7D E0 00 cmp dword ptr [ebp-20h],0 /*3 這裏判斷分配的地址是否爲空,和我們通常在分配完內存後所作的判斷一樣*/
00401C4B 74 11 je main+12Eh (00401c5e)
00401C4D 8D 55 EC lea edx,[n]
00401C50 52 push edx /*obj的構造函數的參數入棧,爲調用構造函數作準備*/
00401C51 8B 4D E0 mov ecx,dword ptr [ebp-20h]
/*參數保存在寄存器cx*/
00401C54 E8 D4 F3 FF FF call @ILT+40(obj::obj) (0040102d) /*呵呵,開始了。進入obj構造函數的調用*/
我們仍然來看能給我們提示的關鍵語句:
(二)printf("this point to %x/n" , (unsigned int)this );
00401A91 8B F4 mov esi,esp
00401A93 8B 55 FC mov edx,dword ptr [ebp-4]
00401A96 52 push edx
00401A97 68 6C 41 41 00 push offset string "this point to %x/n" (0041416c)
/*按函數調用方式__cdecl ,參數(unsigned int)(this)先入棧,在我這裏,從memory中可以看到ebp-4 = 12fee4 ,[ebp-4] = 421110 ,這就是前面通過operator new分配的內存首址,也就是說obj *po此時指向的地址。在obj的構造函數裏,obj *po完成一系列的初始化工作。*/
00401A9C FF 15 D4 62 41 00 call dword ptr [__imp__printf (004162d4)]
00401AA2 83 C4 08 add esp,8
00401AA5 3B F4 cmp esi,esp
00401AA7 E8 26 FD FF FF call _chkesp (004017d2)
從以上分析我們可以看出,obj *po首先由operator new分配內存地址,然後以內存地址作爲參數調用obj構造函數,也就是說在調用構造函數以前,對象的內存佈局就已經完成.基本上我們的分析到這裏就可以結束了.對於c++構造函數背後做的事我們也可以有一個比較清晰的認識了吧!