c++构造函数的背后

原创 2005年04月27日 11:25:00

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++构造函数背后做的事我们也可以有一个比较清晰的认识了吧!

     

C++构造函数初始化列表

  • 2013年04月28日 21:32
  • 3KB
  • 下载

c++构造函数小测验

  • 2014年09月02日 11:19
  • 39KB
  • 下载

C++之带有默认参数值的构造函数

在一个类中 ,如果程序员没有写,任何一个构造函数,则编译器将为该类提供一个默认的构造函数,如果程序员对类的构造函数进行了重载,则编译器将不提供默构造函数,这里需要手动书写一个无参的构造函数, 无参的...

C++构造函数的剖析

  • 2010年05月31日 14:38
  • 754KB
  • 下载

c++构造函数实例质料

  • 2011年05月08日 23:00
  • 30KB
  • 下载

C++中子类构造函数写法总结

C++ 父类 子类 构造函数

C++构造函数重载

  • 2013年04月02日 19:25
  • 4.79MB
  • 下载

C++拷贝构造函数和赋值操作

  • 2012年01月10日 13:51
  • 3KB
  • 下载

理解C++存在继承和组合的对象构造函数调用顺序

前言: Hello,全世界早上好啊,哈哈,9月你好,2015年9月的第一天,也是自己本科生涯的最后一年了,接下来就是校招走上自己的职场,昨天是大四的第一节课,上的是软件工程,挺喜欢的一门课,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:c++构造函数的背后
举报原因:
原因补充:

(最多只允许输入30个字)