c++構造函數的背後

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 newnew操作符)分配了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++構造函數背後做的事我們也可以有一個比較清晰的認識了吧!

     

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章