C++11类内声明时直接赋值(缺省值)方式的初始化时机/类成员初始化顺序

结论

调用构造函数即开始初始化流程:初始化列表(委托构造)->缺省值->构造函数体。
其中,初始化列表的初始化顺序和缺省值初始化顺序由声明顺序决定;构造函数体内由代码顺序决定。
例外: 当constexpr static作为缺省值时,该成员优先由缺省值初始化,然后进行列表初始化。

分析

起因和使用场景

尝试通过

Children() :Children(kDefault) {}

复用单参的构造函数代码,出现了初始化顺序的问题。

代码分析

父类Base,子类Child

情况1

考虑以下代码:

class Base {
 public:
  const int kDefault = 1234;
  Base() : member_(kDefault) {}               // Constructor (1)
  Base(int member) : member_(member) {}       // Constructor (2)

  int member_;
};

class Child : public Base {
 public:
  Child() : Base(kDefault) {}
};

尝试用一父类const成员作为参数,委托构造形式调用父类的构造函数(2),此时,根据结论中初始化顺序:
(1) 父类尚未调用构造函数;
(2) 父类的由缺省值构造的const成员kDefault尚未被构造;

因此虽然kDefault是一个const int成员,其值此时却未被初始化,如果调用委托构造,其构造函数的参数是一个未初始化的值!

情况2

现在考虑另一种方式,如果不用父类的kDefault,由子类自己定义一个kChildDefault,再调用父类构造呢?

class Base {
 public:
  const int kDefault = 1234;
  Base() : member_(kDefault) {}               // Constructor (1)
  Base(int member) : member_(member) {}       // Constructor (2)

  int member_;
};

class Child : public Base {
 public:
  const int kChildDefault = 5678;
  Child() : Base(kChildDefault) {}
};

在调用子类构造函数时,首先执行初始化列表,此时缺省值还没有初始化,因此传递给父类构造的参数也是一个未初始化的值

情况3(特殊情况)

class Base {
 public:
  const int kDefaultA = 100;
  const int kDefaultB;
  Base() : kDefaultB(kDefaultA / 2) {}
}

当初始化列表中,某缺省值(kDefaultA )被另一个需要初始化的值(kDefaultB)依赖时,该缺省值会先被初始化,然后用于初始化依赖其的那个值。此时,两个值都会被正确地初始化。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值