·C++构造函数的幕后工作 - 商帝国咨询 - 五略商书

·C++构造函数的幕后工作

商帝国咨询头像

阅读 20489 | 分类:文章

多年前学习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]
  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;

  可以发现,这行代码果然不再生成对构造函数的调用!


留言区(共0条)

暂无留言,快来抢占沙发~
作者声明:非原创
平台声明:文章及评论仅代表作者本人观点,五略商书系信息发布平台,仅提供信息存储空间服务,如有侵权,请联系13521509118。转载请注明作者和出处:转自五略商书m.shangdiguo.com,作者商帝国咨询!