问题
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 sample = { 1, 2 }
Later, I decide that I need additional data stored in my sampleData
struct, as follows:
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.
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. 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?
回答1:
Initialising variables that way is only supported with 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 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.
回答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).
The relevant language from the C standard is quoted here:
[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.
I am sure someone more motivated than I could find the corresponding language in one of the C++ specs...
Note that this implies that POD scalar elements are initialized as if you wrote "= 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. It also implies that it works recursively; if your struct contains a struct, the inner struct will be properly initialized as well.
回答3:
As a followup to Nemo's answer with the C standardese, here is what the C++03 standard says:
§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:
To value-initialize an object of type
T
means:
- if
T
is a class type with a user-declared constructor, then the default constructor forT
is called (and the initialization is ill-formed ifT
has no accessible default constructor);- if
T
is a non-union class type without a user-declared constructor, then every non-static data member and base-class component ofT
is value-initialized;- if
T
is an array type, then each element is value-initialized;- otherwise, the object is zero-initialized
To zero-initialize an object of type
T
means:
- if
T
is a scalar type, the object is set to the value of0
(zero) converted toT
;- if
T
is a non-union class type, each nonstatic data member and each base-class subobject is zero-initialized;- if
T
is a union type, the object’s first named data member) is zero-initialized;- if
T
is an array type, each element is zero-initialized;- if
T
is a reference type, no initialization is performed.
回答4:
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.
来源:https://stackoverflow.com/questions/6284507/aggregate-initialization-safety-in-c