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

When and how to default-initialize a const variable?

clang++ 不允许 default initialization of a const variable of class-type without a user-defined constructor; g++ is slightly less restrictive (see below). According to this answer,这是因为 POD 类型 "are not initialized by default." 如果我理解正确,这意味着默认初始化不会调用默认构造函数,也不会它是否调用值初始化,因此 POD 类型中的数据成员未被初始化。当然,其中包含未初始化值的 const POD 类型是没有意义的,因为它们 永远不会 被初始化,因此使用起来不安全。

这种情况有几种变体:

  1. 该类型在技术上是 "POD",但不包含数据成员(仅包含函数)。 (clang++ 没有将此视为特例,我认为标准也没有,但 g++ 确实允许它,即使构造函数被标记为 explicit。)
  2. 使用 {} 定义了一个空构造函数。 (这是描述该问题的 clang 页面上推荐的解决方法。)
  3. 默认构造函数已声明 =default。 (从 C++11 开始;该类型仍被视为 POD,因此编译器和标准均未将其视为特例。)
  4. 聚合初始化是使用 {} 显式调用的,它(如果我理解正确的话)变成了值初始化。 (C++11 以后;两个编译器——我认为是标准——都允许这样做。)

在第一种情况下,不能有 未初始化的 成员,因此不清楚为什么 class 本身的任何实例化都会被视为 "uninitialized,"不管是不是const。由于 g++ 允许这种行为,使用它安全吗?为什么被clang++和标准禁止? (还有其他情况 g++ 允许 POD 默认初始化而 clang++ 不允许吗?)

在第二种和第三种情况下,使用 {} 而不是 =default 的要求对我来说似乎很奇怪。 编辑: this question 很好地解释了区别,所以我删除了问题中询问区别的部分。 (不过,我仍然认为这是该语言的一个非常令人困惑的方面。)

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

Since g++ allows this behavior, is it safe to use?

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

Why is it prohibited by clang++ and the standard?

大概是委员会在将 "user-provided constructor required" 规则放入 C++98 时没有考虑它,或者认为特殊外壳的空 POD 类 不值得规范复杂; clang++ 只是遵循标准。但是,标准是 likely going to change 更普遍地允许您编写 const Foo f; 只要构造函数实际上会初始化每个子对象。

Finally, will Foo f{}; always zero-initialize members of built-in type if Foo::Foo(void) is {}, =default, or implicitly-declared?

后两者是的。不,首先。那一个算作用户提供的,因此值初始化在调用默认构造函数之前不会执行零初始化。