C++11 中默认初始化的含义发生了变化?

Meaning of default initialization changed in C++11?

提问人:Adrian McCarthy 提问时间:3/7/2014 最后编辑:sbiAdrian McCarthy 更新时间:5/30/2014 访问量:4532

问:

C++2003 8.5/5 说:

默认初始化 T 类型的对象意味着:

— 如果 T 是非 POD 类类型(子句 9),则调用 T 的默认构造函数(初始化为 如果 T 没有可访问的默认构造函数,则格式不正确);

— 如果 T 是数组类型,则每个元素都是默认初始化的;

— 否则,对象初始化为

[着重号是后加的。

C++2011 标准将最后一项更改为

— 否则,不执行初始化

对于某些程序来说,这似乎是一个重大变化。这是故意的吗?

编辑

以下是一些激发此问题的代码:

class Foo {
  public:
    Foo() : m_values() {}

    int m_values[3];
};

在 C++11 之前,我认为在默认构造函数中明确提及 会默认初始化该数组。由于数组的元素是标量,我预计这意味着这些值都设置为 0。m_values

在 C++11 中,似乎不再能保证这会发生。但也许,正如 Mooing Duck 在评论中指出的那样,也许这不再是默认初始化的情况,而是保留预期行为的其他形式。欢迎引用。

C ++11 初始化 语言-律师 C++-常见问题

评论

0赞 Victor 3/7/2014
对象未初始化。因此,它们是未初始化的对象。
1赞 Mooing Duck 3/7/2014
@Victor:他知道。他的观点是,从初始化到未初始化的更改是一个重大更改。
3赞 Mooing Duck 3/7/2014
我记得听说 C++03 没有“值初始化”与“默认初始化”与“零初始化”之类的东西。有没有可能以前默认初始化的东西现在初始化为零,这使得它成为一个不中断的更改?
2赞 3/7/2014
m_values应初始化值,因为它是带有空括号的成员初始值设定项列表的一部分。

答:

25赞 James Kanze 3/7/2014 #1

最终效果几乎相同。在 C++03 中,默认初始化的使用仅限于非 POD 类类型,因此最后一点从未应用。在 C++11 中,该标准通过消除有关使用默认初始化的位置的条件来简化措辞,并更改了默认初始化的定义以涵盖所有情况,以对应之前发生的情况。

评论

0赞 Casey 3/7/2014
具体来说,C++03 8.5/9:如果没有为对象指定初始值设定项,并且该对象是(可能是 cv 限定的)非 POD 类类型(或其数组),则该对象应默认初始化;如果对象是 const 限定类型,则基础类类型应具有用户声明的默认构造函数。否则,如果未为非静态对象指定初始值设定项,则该对象及其子对象(如果有)具有不确定的初始值;如果对象或其任何子对象是常量限定类型,则程序格式不正确。
0赞 Casey 3/7/2014
vs. C++11 8.5/11:如果未为对象指定初始值设定项,则默认初始化该对象;如果未执行初始化,则具有自动或动态存储持续时间的对象具有不确定的值。
2赞 Adrian McCarthy 3/7/2014
我不太明白这个答案。你是说由于示例中的数组是 POD,因此默认初始化从未应用过,即使在 C++03 中也没有?你能澄清一下吗?如果我构造如上所示的 a,则 中的值是 0 还是不确定?m_valuesFoom_values
2赞 Adrian McCarthy 3/20/2014
@JamesKanze:你的回答看起来对很多人都有帮助,但我仍然有我之前评论的问题。如果你能把这些都弄清楚,我很乐意接受。
0赞 Chris Dodd 8/16/2017
@AdrianMcCarthy:由于构造器中的显式,数组在任何版本的 C++ 中都不会默认初始化;它是初始化的值(在 C++03 和 11 中是相同的)。如果不存在,则数组在 C++03 中取消初始化,在 C++11 中默认初始化。m_values()
3赞 user1508519 3/7/2014 #2

根据 cppreference.com(因为它使用比标准更友好的语言):

默认初始化在三种情况下执行:

3) 当基类或非静态数据成员未在 构造函数初始值设定项列表,并调用该构造函数。

值初始化在三种情况下执行:

3,7) 初始化非静态数据成员或基类时 使用带有一对空括号的成员初始值设定项or braces (since C++11)

请注意,C++11 部分属于 ,而不是整个段落。or braces

和:

对 T 类型的对象进行值初始化意味着:
— 如果 T 是数组类型,则每个元素都经过值初始化;
— 否则,对象初始化为零

因此,在 C++11 中,默认初始化不会对成员进行零初始化,但值初始化会。

2赞 MWid 5/30/2014 #3

严格来说,default-initialize 的定义已从 C++03 更改为 C++11。但也必须考虑到,当一个对象被_default-initialize_d时,情况发生了变化:

§8.5p9 C++03 声明:

如果未为对象指定初始值设定项,并且该对象是(可能是 cv 限定的)非 POD 类类型(或其数组),则该对象应默认初始化;如果对象是 const 限定类型,则基础类类型应具有用户声明的默认构造函数。否则,如果未为非静态对象指定初始值设定项,则该对象及其子对象(如果有)具有不确定的初始值;如果对象或其任何子对象是常量限定类型,则程序格式不正确。

§8.5p11 C++11 声明:

如果未为对象指定初始值设定项,则该对象将默认初始化;如果未执行初始化,则具有自动或动态存储持续时间的对象具有不确定的值。

正如@JamesKanze已经指出的,当没有为非 POD 类类型的对象指定初始值设定项时,会在 C++03 中执行默认初始化。在 C++11 中,如果未指定初始值设定项,则默认初始化对象(任意类型)。由于此更改,还必须更改默认初始化的定义,以便与 C++03 兼容。


您的示例与 default-initialization 无关。一直以来,其初始值设定项是一组空括号的对象都是值初始化的。