Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / C++类一定有构造函数吗

1:任何类如果没有定义默认构造函数,就会合成出来?2:合成出来的默认构造函数会明确设定类内每一个成员的值?3:如何去证明呢?如果你对1、2回答的都是不是,请跳过阅读,以免浪费你的时间对于问题1与2其实答案都是未必,C++标准是这样写的默认构造函数是由编译器在需要的时候将其合成出来,这里强调的是需要,而非必需,以程序示例:#include<iostream>
#include<string>
using namespace std;
class A
{
public:
  char *ptr;
  //string str;
};
int main()
{
 A b;
 b.ptr=NULL;
 return 0;
}这个程序本身没什么好讲的,能讲的就是其汇编代码,调试状态下进入汇编代码如下:11: {
00401030 push        ebp
00401031 mov       ebp,esp
00401033 sub       esp,44h
00401036 push        ebx
00401037 push        esi
00401038 push        edi
00401039 lea       edi,[ebp-44h]
0040103C mov       ecx,11h
00401041 mov       eax,0CCCCCCCCh
00401046 rep stos    dword ptr [edi]
12:     A b;
13:     b.ptr=NULL;
00401048 mov       dword ptr [ebp-4],0
14:     return 0;
0040104F xor       eax,eax
15: }你能找到构造函数调用的地方吗即A::A(),:),找不到吧,因为压根就没有构造函数,这个类就相当于一个整形变量(存储上相似,用法上不同),其空间是堆栈ebp+4这里的4个字节将程序注释中的 //string str;去掉,再次进入汇编看看,代码如下:10: int main()
11: {
00401070 push        ebp
00401071 mov       ebp,esp
00401073 sub       esp,58h
00401076 push        ebx
00401077 push        esi
00401078 push        edi
00401079 lea       edi,[ebp-58h]
0040107C mov       ecx,16h
00401081 mov       eax,0CCCCCCCCh
00401086 rep stos    dword ptr [edi]
12:     A b;
00401088 lea       ecx,[ebp-14h]
0040108B call        @ILT+15(A::A) (00401014)
13:     b.ptr=NULL;
00401090 mov       dword ptr [ebp-14h],0
14:     return 0;
00401097 mov       dword ptr [ebp-18h],0
0040109E lea       ecx,[ebp-14h]
004010A1 call        @ILT+30(A::~A) (00401023)
004010A6 mov       eax,dword ptr [ebp-18h]
15: }看看,我们的构造函数出现了吧A:A() :),为什么会出现呢?
因为类里面有一个类叫string,我们跟踪发现string类定义在include/xstring里,其形式如下:typedef basic_string<char, char_traits<char>, allocator<char> >
 string;这是一个模板类,属于STL范畴,不信你看看SGI STL源码,在机会再讲,继教跟踪,你会发现basic_string有一系列的构造函数,如下: explicit basic_string(const _A& _Al = _A())
  : allocator(_Al) {_Tidy(); }
 basic_string(const _Myt& _X)
  : allocator(_X.allocator)
  {_Tidy(), assign(_X, 0, npos); }
 basic_string(const _Myt& _X, size_type _P, size_type _M,
  const _A& _Al = _A())
  : allocator(_Al) {_Tidy(), assign(_X, _P, _M); }
 basic_string(const _E *_S, size_type _N,
  const _A& _Al = _A())
  : allocator(_Al) {_Tidy(), assign(_S, _N); }
 basic_string(const _E *_S, const _A& _Al = _A())
  : allocator(_Al) {_Tidy(), assign(_S); }
 basic_string(size_type _N, _E _C, const _A& _Al = _A())
  : allocator(_Al) {_Tidy(), assign(_N, _C); }其实重要的是第一个构造函数,因为此处调用就是它,给basic_string分配一个内存分配管理器:)明白了吧,此处有是因为类里面有一个string类的对象,别人属于你,别人有自已的构造函数,需要为其赋一个初始值,你总不能不让吧,于是编译器就合成一个默认的构造函数,调用string里的构造函数,为string对像置一个初始状态构造函数的确是不一定会有的,而且类里的一些内置类型默认构造函数也不会给其设定一个默认值的,不信你再看看汇编,哪里有对ptr的赋值:)有四种情况编译器会为合成默认构造函数1:含有默认默认/构造函数的成员类对象2:带有默认/构造函数的基类对象3: 含有虚函数的类4:继承虚基类的类可以参考此书《深入理解C++对象模型》第二章 下载见 http://www.linuxidc.com/Linux/2012-03/56159.htm