何时以及如何默认初始化const变量?

时间:2015-06-05 03:24:32

标签: c++ c++11 constructor default-constructor

clang++不允许default initialization of a const variable of class-type without a user-defined constructor; g++限制性稍差(见下文)。根据{{​​3}},这是因为POD类型“默认情况下未初始化”。如果我理解正确,这意味着默认初始化不会调用默认构造函数,也不会调用值初始化,因此POD类型中的数据成员不会被初始化。当然,使用带有未初始化值的const POD类型是没有意义的,因为它们永远不会被初始化,因此使用起来不安全。

这种情况有一些变种:

  1. 类型在技术上是“POD”,但不包含数据成员(仅限函数)。 (clang++不会将此视为特殊情况,我认为也不是标准,但g++确实允许它,即使构造函数标记为explicit。)
  2. 使用{}定义空构造函数。 (这是描述问题的clang页面上的建议解决方法。)
  3. 默认构造函数声明为=default。 (C ++ 11以后;类型仍然被认为是POD,因此编译器和标准都不会将其视为特殊情况。)
  4. 使用{}显式调用聚合初始化,如果我理解正确,则会变为值初始化。 (C ++ 11以后;两个编译器 - 我认为,标准 - 允许这个。)
  5. 在第一种情况下,可能没有未初始化的成员,因此不清楚为什么类本身的任何实例化都将被视为“未初始化”,无论它是否为{{1} }。由于const允许这种行为,使用它是否安全?为什么g++和标准禁止它? (还有其他情况clang++允许POD默认初始化g++没有吗?)

    在第二和第三种情况下,使用clang++代替{}的要求对我来说似乎很奇怪。 编辑: this answer很好地解释了这个差异,所以我已经删除了询问区别的部分问题。 (尽管如此,我仍然认为这是该语言非常令人困惑的方面。)

    最后,如果=defaultFoo f{}Foo::Foo(void)或隐式声明,{}是否始终对初始化内置类型的成员进行初始化?

1 个答案:

答案 0 :(得分:5)

  

由于g ++允许这种行为,使用它是否安全?

安全在什么意义上?目前显然不便携。但是,它不会给你带来意想不到的g ++结果。

  

为什么clang ++和标准禁止它?

大概是委员会在C ++ 98中提出“用户提供的构造函数”规则时没有想到它,或者认为特殊套管空POD类不值得规范复杂性; clang ++只是遵循标准。但是,标准为likely going to change,更通常允许您编写const Foo f;,只要构造函数实际上将初始化每个子对象。

  

最后,Foo f{};将始终对初始化内置成员进行零初始化   如果Foo::Foo(void){}=default或隐式声明,请输入类型?

对后两者是肯定的。不是第一个。那个计为用户提供的,因此值初始化在调用默认构造函数之前不会执行零初始化。