linux c 构造函数,C++类一定有构造函数吗

1:任何类如果没有定义默认构造函数,就会合成出来?

2:合成出来的默认构造函数会明确设定类内每一个成员的值?

3:如何去证明呢?

如果你对1、2回答的都是不是,请跳过阅读,以免浪费你的时间

对于问题1与2其实答案都是未必,C++标准是这样写的默认构造函数是由编译器在需要的时候将其合成出来,这里强调的是需要,而非必需,以程序示例:

#include

#include

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, allocator >

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:继承虚基类的类

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值