简体   繁体   English

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

[英]Aggregate Initialization Safety in C++

Suppose I have the following struct:假设我有以下结构:

struct sampleData
{
       int x;
       int y;
};

And when used, I want to initialize variables of sampleData type to a known state.并且在使用时,我想将sampleData类型的变量初始化为已知的 state。

sampleData sample = { 1, 2 } 

Later, I decide that I need additional data stored in my sampleData struct, as follows:后来,我决定需要将其他数据存储在我的sampleData结构中,如下所示:

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

It is my understanding that the two field initialization left over from my pre- z data structure is still a valid statement, and will be compiled., populating the missing fields with default values.据我了解,从我的 pre- z数据结构中遗留下来的两个字段初始化仍然是一个有效的语句,并且将被编译,用默认值填充缺失的字段。

Is this understanding correct?这种理解正确吗? I have been working recently in Ada, which also allows aggregate initialization, but which would flag a similar issue as a compilation error.我最近一直在 Ada 工作,它也允许聚合初始化,但会将类似的问题标记为编译错误。 Assuming that my assumptions about the C++ code above are correct, is there a language construct which would recognize missing initialization values as an error?假设我对上面 C++ 代码的假设是正确的,是否有一种语言结构可以将缺少的初始化值识别为错误?

Initialising variables that way is only supported with Aggregate Classes .只有Aggregate Classes支持以这种方式初始化变量。

If you add constructor(s) then then problem goes away, but you'll need to change the syntax a little and you lose the ability to store the struct in a union (among other things).如果您添加构造函数,那么问题就会消失,但是您需要稍微更改语法,并且您将失去将struct存储在union中的能力(除其他外)。

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

sampleData sample( 1, 2 );

Adding z (and changing the constructor) will mark sample( 1, 2 ) as a compile error.添加z (并更改构造函数)会将sample( 1, 2 )标记为编译错误。

Yes, any elements you leave off of the initialization list will be initialized to zero (for POD scalar types) or using their default constructor (for classes).是的,您离开初始化列表的任何元素都将被初始化为零(对于 POD 标量类型)或使用它们的默认构造函数(对于类)。

The relevant language from the C standard is quoted here :此处引用了 C 标准中的相关语言:

[6.7.8.21] If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration. [6.7.8.21] 如果大括号括起来的列表中的初始值设定项少于聚合的元素或成员,或者用于初始化已知大小数组的字符串文字中的字符少于数组中的元素,则聚合的其余部分应隐式初始化,与具有 static 存储持续时间的对象相同。

I am sure someone more motivated than I could find the corresponding language in one of the C++ specs...我确信有人比我在 C++ 规范之一中找到相应的语言更有动力......

Note that this implies that POD scalar elements are initialized as if you wrote "= 0".请注意,这意味着 POD 标量元素的初始化就像您写了“= 0”一样。 Which means it will correctly initialize pointers to NULL and floats to 0.0 even if their representations do not happen to be all-zero bytes.这意味着它将正确初始化指向 NULL 的指针并浮动到 0.0,即使它们的表示不是全零字节。 It also implies that it works recursively;这也意味着它是递归工作的; if your struct contains a struct, the inner struct will be properly initialized as well.如果您的结构包含一个结构,则内部结构也将被正确初始化。

As a followup to Nemo's answer with the C standardese, here is what the C++03 standard says:作为 Nemo 对 C 标准的回答的后续,这里是 C++03 标准所说的:

§8.5.1/7: §8.5.1/7:

If there are fewer initializers in the list than there are members in the aggregate, then each member not explicitly initialized shall be value-initialized.如果列表中的初始化器少于聚合中的成员,则每个未显式初始化的成员都应进行值初始化。

§8.5/5: §8.5/5:

To value-initialize an object of type T means:T类型的 object 进行值初始化意味着:

  • if T is a class type with a user-declared constructor, then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);如果T是具有用户声明的构造函数的 class 类型,则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化格式错误);
  • if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized;如果T是没有用户声明的构造函数的非联合 class 类型,则T的每个非静态数据成员和基类组件都是值初始化的;
  • if T is an array type, then each element is value-initialized;如果T是一个数组类型,那么每个元素都是值初始化的;
  • otherwise, the object is zero-initialized否则,object 被零初始化

To zero-initialize an object of type T means:T类型的 object 进行零初始化意味着:

  • if T is a scalar type, the object is set to the value of 0 (zero) converted to T ;如果T是标量类型,则将 object 设置为转换为T的值0 (零);
  • if T is a non-union class type, each nonstatic data member and each base-class subobject is zero-initialized;如果T是非联合 class 类型,则每个非静态数据成员和每个基类子对象都初始化为零;
  • if T is a union type, the object's first named data member) is zero-initialized;如果T是联合类型,则对象的第一个命名数据成员)初始化为零;
  • if T is an array type, each element is zero-initialized;如果T是数组类型,则每个元素都初始化为零;
  • if T is a reference type, no initialization is performed.如果T是引用类型,则不执行初始化。

Why not use为什么不使用

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

? ?

But you'd still run into the problem of z being initialized to an unpredictable value, so it's better to define a constructor which sets all variables to well defined values.但是您仍然会遇到z被初始化为不可预测值的问题,因此最好定义一个将所有变量设置为明确定义的值的构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM