在上一篇文章中,我们看了下简单的默认构造函数(没有成员变量的类)的构造函数的反汇编代码。这次我们来看一下如果一个类如果有默认构造函数的成员变量的话,这个类的默认构造函数会是什么样子。注:在这篇文章中的默认构造函数都是空的构造函数,就像下面代码的构造函数:
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。
这就是这次记录的东西了。嘿嘿,比起上次懒了,隔了好久才写这一篇。最近经历了不少东西,内心在骚动。以前想写博客是个很简单的事,写的时候才发现真心不是那回事。好好努力吧。
请大家多多指教,板砖尽管扔,不扔脸一切好说。