C ++中的聚合初始化安全性

时间:2011-06-08 20:00:21

标签: c++ ada aggregate-initialization

假设我有以下结构:

struct sampleData
{
       int x;
       int y;
};

使用时,我想将sampleData类型的变量初始化为已知状态。

sampleData sample = { 1, 2 } 

稍后,我决定需要在sampleData结构中存储其他数据,如下所示:

struct sampleData
{
       int x;
       int y;
       int z;
};

我的理解是,从我的前z数据结构遗留下来的两个字段初始化仍然是一个有效的语句,并且将被编译。使用默认值填充缺少的字段。

这种理解是否正确?我最近一直在Ada工作,它也允许聚合初始化,但是会将类似的问题标记为编译错误。假设我对上面的C ++代码的假设是正确的,是否有一种语言结构可以将缺少的初始化值识别为错误?

4 个答案:

答案 0 :(得分:5)

只有Aggregate Classes支持以这种方式初始化变量。

如果你添加了构造函数,那么问题就会消失,但是你需要稍微改变一下语法,你就失去了将struct存储在union中的能力。的东西)。

struct sampleData
{
    sampleData(int x, int y) : x(x), y(y) {}
    int x;
    int y;
};

sampleData sample( 1, 2 );

添加z(并更改构造函数)会将sample( 1, 2 )标记为编译错误。

答案 1 :(得分:4)

是的,您从初始化列表中留下的任何元素都将初始化为零(对于POD标量类型)或使用其默认构造函数(对于类)。

C标准中的相关语言引用here

  

[6.7.8.21]如果括号括起的列表中的初始值设定项少于聚合的元素或成员,或者用于初始化已知大小的数组的字符串文字中的字符数少于其中的元素。对于数组,聚合的其余部分应与具有静态存储持续时间的对象隐式初始化。

我确信有人比我在其中一个C ++规范中找到相应的语言更有动力......

请注意,这意味着POD标量元素已初始化,就像您编写“= 0”一样。这意味着它将正确地初始化指向NULL的指针并浮动到0.0,即使它们的表示不是全零字节。它还意味着它以递归方式工作;如果你的struct包含一个struct,那么内部struct也会被正确初始化。

答案 2 :(得分:4)

作为Nemo对C标准的回答,这是C ++ 03标准所说的:

第8.5.1节/ 7:

  

如果列表中的初始值设定项少于聚合中的成员,则未显式初始化的每个成员都应进行值初始化。

第8.5节/ 5:

  

value-initialize T类型的对象意味着:

     
      
  • 如果T是具有用户声明的构造函数的类类型,则调用T的默认构造函数(如果T没有可访问的默认值,则初始化不正确构造函数);
  •   
  • 如果T是没有用户声明的构造函数的非联合类类型,那么T的每个非静态数据成员和基类组件都是值初始化的;
  •   
  • 如果T是数组类型,则每个元素都是值初始化的;
  •   
  • 否则,对象为零初始化
  •   
     

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

     
      
  • 如果T是标量类型,则将对象设置为0(零)转换为T的值;
  •   
  • 如果T是非联合类类型,则每个非静态数据成员和每个基类子对象都是零初始化的;
  •   
  • 如果T是联合类型,则对象的第一个命名数据成员)是零初始化的;
  •   
  • 如果T是数组类型,则每个元素都是零初始化的;
  •   
  • 如果T是引用类型,则不执行初始化。
  •   

答案 3 :(得分:-2)

为什么不使用

sampleData sample = { x: 1, y:2 } ;

但是你仍然遇到z初始化为不可预测值的问题,因此最好定义一个构造函数,将所有变量设置为明确定义的值。