C/C++日常学习总结(第十三篇)默认构造函数内部再调用带参的构造函数

struct  CLS

{

   int m_i;

   CLS(int i):m_i(i)

   {}

   CLS()

   {

     CLS(0);

   }

};


CLS obj;

cout<<obj.m_i<<endl;


        想必大家可能都见过这道题目,问打印出来的结果是不是0?既然问了,那么答案可能是要值得推敲的,但是为什么?很多网上答案都是说默认构造函数调用带参数的构造函数是非编译器所为,是人为调用,所以不会调用初始化列表,所以就不能初始化m_i的值,那么打印出来的结果自然很可能不是0;

 

        本人对于上面的答案是半信半疑,即使是这样,总归还是没有说出根本原因,参考了下面的一篇文章,我才觉得是这么回事。

        参考地址:http://www.cnblogs.com/chio/archive/2007/10/20/931043.html

       

       以下为借鉴: 

       我们知道,当定义一个对象时,会按顺序做2件事情:
       1)分配好内存(非静态数据成员是未初始化的)
       2)调用构造函数(构造函数的本意就是初始化非静态数据成员)

       显然上面代码中,CLS obj;这里已经为obj分配了内存,然后调用默认构造函数,但是默认构造函数还未执行完,却调用了另一个构造函数,这样相当于产生了一个匿名的临时CLS对象,它调用CLS(int)构造函数,将这个匿名临时对象自己的数据成员m_i初始化为0;但是obj的数据成员并没有得到初始化。于是obj的m_i是未初始化的,因此其值也是不确定的

      从这里,我们归纳如下:
     1)在c++里,由于构造函数允许有默认参数,使得这种构造函数调用构造函数来重用代码的需求大为减少
     2)如果仅仅为了一个构造函数重用另一个构造函数的代码,那么完全可以把构造函数中的公共部分抽取出来定义一个成员函数(推荐为private),然后在每个需要这个代码的构造函数中调用该函数即可
     3)偶尔我们还是希望在类的构造函数里调用另一个构造函数,可以按下面方式做:
在构造函数里调用另一个构造函数的关键是让第二个构造函数在第一次分配好的内存上执行,而不是分配新的内存,这个可以用标准库的placement new做到:

     先看看标准库中placement new的定义

inline void *__cdecl operator new(size_t, void *_P)
 {
     return (_P); 
 } 


    可见没有分配新的内存。

    正确的方式:

  struct CLS
 {
     int m_i;
     CLS( int i ) : m_i(i){}
     CLS()
     {
         new (this)CLS(0);
     }
 };



 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值