在C ++ 11中更改了默认初始化的含义?

时间:2014-03-06 18:39:10

标签: c++ c++11 initialization language-lawyer c++-faq

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之前,我认为在默认构造函数中明确提到m_values default-initialize 该数组。由于数组的元素是标量,我希望这意味着值都被设置为0。

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

3 个答案:

答案 0 :(得分:22)

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

答案 1 :(得分:3)

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

  

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

     
    

3)当a中没有提到基类或非静态数据成员时     构造函数初始化列表和该构造函数被调用。

  
     

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

     
    

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

的成员初始值设定项   

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

  

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

所以在C ++ 11中,默认初始化不会对成员进行零初始化,但值初始化会这样做。

答案 2 :(得分:2)

严格地说, default-initialize 的定义已从C ++ 03更改为C ++ 11。但是还要考虑到对象是_default-initialize_d的情况发生了变化:

§8.5p9C++ 03陈述:

  

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

§8.5p11C++ 11陈述:

  

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

正如@JamesKanze已经指出的那样,当没有指定非POD类类型的对象的初始化器时,在C ++ 03中执行 default-initialization 。在C ++ 11中,如果没有指定初始化程序,则对象(任意类型)是默认初始化。由于此更改,还必须更改 default-initialize 的定义,以便与C ++ 03兼容。


您的示例与默认初始化无关。始终如此,其初始值设定项为空括号的对象是值初始化