• 深入C++的默认构造函数2成员变量有默认构造函数


    上一篇文章中,我们看了下简单的默认构造函数(没有成员变量的类)的构造函数的反汇编代码。这次我们来看一下如果一个类如果有默认构造函数的成员变量的话,这个类的默认构造函数会是什么样子。注:在这篇文章中的默认构造函数都是空的构造函数,就像下面代码的构造函数:

    1 class A
    2 {
    3 public:
    4 A(){};
    5 void print()
    6 {
    7     std::cout << "I am A" << std::endl;
    8 }
    9 };

    在开始看代码前,我们先思考下拥有成员变量(有默认构造函数)的类的构造函数的行为。首先我们想一下类的构造函数的作用。类的构造函数的作用是对这个类进行初始化(initialization),即为此类的实例分配内存等资源。这样的话,默认构造函数应该会自动调用成员变量的构造函数。那是不是这样呢,代码来验证。

    示例代码:

     1 #include <iostream>
     2 
     3 class A
     4 {
     5 public:
     6     A(){};
     7     void printA()
     8     {
     9         std::cout << "I am A" << std::endl;
    10     }
    11 };
    12 
    13 class B
    14 {
    15 public:
    16     B(){};
    17     void printB()
    18     {
    19         std::cout << "I am B" << std::endl;
    20     }
    21 };
    22 
    23 class C
    24 {
    25 public:
    26     C(){};
    27     void printC()
    28     {
    29         std::cout << "I am C" << std::endl;
    30     }
    31 private:
    32     A m_nA;
    33     B m_nB;
    34 };
    35 
    36 int main()
    37 {
    38     C c;
    39     c.printC();
    40     std::cin.get();
    41     return 0;
    42 }; 

    反汇编的代码:

    1  C c;
    2 00F814EE  lea         ecx,[c] 
    3 00F814F1  call        C::C (0F81267h) 
    4     c.printC();
    5 00F814F6  lea         ecx,[c] 
    6 00F814F9  call        C::printC (0F81271h) 
    7     std::cin.get();

    我们查看C::C () 的代码:

     1 00F81560  push        ebp  
     2 00F81561  mov         ebp,esp 
     3 00F81563  sub         esp,0CCh 
     4 00F81569  push        ebx  
     5 00F8156A  push        esi  
     6 00F8156B  push        edi  
     7 00F8156C  push        ecx  
     8 00F8156D  lea         edi,[ebp-0CCh] 
     9 00F81573  mov         ecx,33h 
    10 00F81578  mov         eax,0CCCCCCCCh 
    11 00F8157D  rep stos    dword ptr es:[edi] 
    12 00F8157F  pop         ecx  
    13 00F81580  mov         dword ptr [ebp-8],ecx 
    14 00F81583  mov         ecx,dword ptr [this] 
    15 00F81586  call        A::A (0F8126Ch) 
    16 00F8158B  mov         ecx,dword ptr [this] 
    17 00F8158E  add         ecx,1 
    18 00F81591  call        B::B (0F81122h) 
    19 00F81596  mov         eax,dword ptr [this] 
    20 00F81599  pop         edi  
    21 00F8159A  pop         esi  
    22 00F8159B  pop         ebx  
    23 00F8159C  add         esp,0CCh 
    24 00F815A2  cmp         ebp,esp 
    25 00F815A4  call        @ILT+425(__RTC_CheckEsp) (0F811AEh) 
    26 00F815A9  mov         esp,ebp 
    27 00F815AB  pop         ebp  
    28 00F815AC  ret                    

    在反汇编的代码中可以看到,C的构造函数调用了A和B的默认构造函数。调用的A和B的顺序是和C中声明A、B的顺序是一致的。

    看来结果和前面想的是一样的,再找些理论基础吧:

    "如果class A 内含一个或一个以上的 member class objects, 那么 class A 的每一个constructor必须调用每一个 member class objects 的 default constructor"。编译器会扩张已存在的 constructors,在其中安插一些代码,使得 user code 在被执行之前,先调用必要的 default constructors. ” -----《深度探索C++对象模型》-P42。

    这就是这次记录的东西了。嘿嘿,比起上次懒了,隔了好久才写这一篇。最近经历了不少东西,内心在骚动。以前想写博客是个很简单的事,写的时候才发现真心不是那回事。好好努力吧。

    请大家多多指教,板砖尽管扔,不扔脸一切好说。

  • 相关阅读:
    [BZOJ 2820]YY的GCD
    [POI 2007]ZAP-Queries
    [USACO 04OPEN]MooFest
    [HAOI 2011]Problem b
    [COGS 2258][HZOI 2015]复仇的序幕曲
    [UOJ 41]【清华集训2014】矩阵变换
    [POJ 3487]The Stable Marriage Problem
    [POJ 3252]Round Numbers
    [COGS 1799][国家集训队2012]tree(伍一鸣)
    [SDOI 2011]计算器
  • 原文地址:https://www.cnblogs.com/yetuweiba/p/2698924.html
Copyright © 2020-2023  润新知