深入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。

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

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

posted @ 2012-09-23 14:59  yetuweiba  阅读(1738)  评论(2编辑  收藏  举报