提问人:Adrian McCarthy 提问时间:3/7/2014 最后编辑:sbiAdrian McCarthy 更新时间:5/30/2014 访问量:4532
C++11 中默认初始化的含义发生了变化?
Meaning of default initialization changed in C++11?
问:
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++03 中,默认初始化的使用仅限于非 POD 类类型,因此最后一点从未应用。在 C++11 中,该标准通过消除有关使用默认初始化的位置的条件来简化措辞,并更改了默认初始化的定义以涵盖所有情况,以对应之前发生的情况。
评论
m_values
Foo
m_values
m_values()
根据 cppreference.com(因为它使用比标准更友好的语言):
默认初始化在三种情况下执行:
3) 当基类或非静态数据成员未在 构造函数初始值设定项列表,并调用该构造函数。
值初始化在三种情况下执行:
3,7) 初始化非静态数据成员或基类时 使用带有一对空括号的成员初始值设定项
or braces (since C++11)
请注意,C++11 部分属于 ,而不是整个段落。or braces
和:
对 T 类型的对象进行值初始化意味着:
— 如果 T 是数组类型,则每个元素都经过值初始化;
— 否则,对象初始化为零
因此,在 C++11 中,默认初始化不会对成员进行零初始化,但值初始化会。
严格来说,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 无关。一直以来,其初始值设定项是一组空括号的对象都是值初始化的。
评论
m_values
应初始化值,因为它是带有空括号的成员初始值设定项列表的一部分。