您的位置:首页 > 编程语言 > C语言/C++

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

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

class A
{
public:
A(){};
void print()
{
std::cout << "I am A" << std::endl;
}
};


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

示例代码:

#include <iostream>

class A
{
public:
A(){};
void printA()
{
std::cout << "I am A" << std::endl;
}
};

class B
{
public:
B(){};
void printB()
{
std::cout << "I am B" << std::endl;
}
};

class C
{
public:
C(){};
void printC()
{
std::cout << "I am C" << std::endl;
}
private:
A m_nA;
B m_nB;
};

int main()
{
C c;
c.printC();
std::cin.get();
return 0;
};


反汇编的代码:

C c;
00F814EE  lea         ecx,[c]
00F814F1  call        C::C (0F81267h)
c.printC();
00F814F6  lea         ecx,[c]
00F814F9  call        C::printC (0F81271h)
std::cin.get();


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

00F81560  push        ebp
00F81561  mov         ebp,esp
00F81563  sub         esp,0CCh
00F81569  push        ebx
00F8156A  push        esi
00F8156B  push        edi
00F8156C  push        ecx
00F8156D  lea         edi,[ebp-0CCh]
00F81573  mov         ecx,33h
00F81578  mov         eax,0CCCCCCCCh
00F8157D  rep stos    dword ptr es:[edi]
00F8157F  pop         ecx
00F81580  mov         dword ptr [ebp-8],ecx
00F81583  mov         ecx,dword ptr [this]
00F81586  call        A::A (0F8126Ch)
00F8158B  mov         ecx,dword ptr [this]
00F8158E  add         ecx,1
00F81591  call        B::B (0F81122h)
00F81596  mov         eax,dword ptr [this]
00F81599  pop         edi
00F8159A  pop         esi
00F8159B  pop         ebx
00F8159C  add         esp,0CCh
00F815A2  cmp         ebp,esp
00F815A4  call        @ILT+425(__RTC_CheckEsp) (0F811AEh)
00F815A9  mov         esp,ebp
00F815AB  pop         ebp
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。

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

请大家多多指教,板砖尽管扔,不扔脸一切好说。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: