Consider the following code in which we initialize part of D
based on another part of D
:
struct c {
c() : D{rand(), D[0]} {}
int D[2];
};
int main() {
c C;
assert(C.D[0] == C.D[1]);
}
Is the above program well-defined? Can we safely use one part of the same array to initialize another part of it?
When aggregates (including arrays) are initialized from a braced list, each aggregate element is initialized from the corresponding element of the list ("in increasing subscript or member order"). Even though I can't find an exact rule that says that each element initialization is sequenced after the preceding one, there's an example in the Standard that clearly implies that this is the intended meaning. The example is in [dcl.init.aggr]:
struct S { int a; const char* b; int c; int d = b[a]; }; S ss = { 1, "asdf" };
initializes
ss.a
with1
,ss.b
with"asdf"
,ss.c
with the value of an expression of the formint{}
(that is,0
), andss.d
with the value ofss.b[ss.a]
(that is,’s’
)
Can array members be initialized self-referentially?
Yes.
struct c {
int a[3];
c() : a{4, a[0], 3} {} // a[0] is initialized to 4.
// a[1] is initialized to whatever a[0] is. (4)
// a[2] is initialized to 3.
};
But consider this example:
struct c {
int a[3];
c() : a{a[1], 4, a[1]} {} // a[0] is initialized to whatever a[1] is.(Garbage value)
// a[1] is initialized to 4.
// a[2] is initialized to what a[1] is now (4).
};
Here the first element in a
will be whatever value is in a[1]
,
which will most likely be garbage value.
Second element is initialized to 4
and third element is initialized
to what is now in a[1]
, which is the value 4
.
Also, when you don't list all the elements in the array inside the {}
,
elements that aren't listed, will be default initialized:
struct c {
int a[5]; // notice the size
c() : a{a[1], 2, 3, 4}{} // a[0] will get value that is in a[1]
// but since a[1] has garbage value,
// it will be default initialized to 0.
// a[1] = 2
// a[2] = 3
// a[3] = 4
// a[4] is not listed and will get 0.
};
However, listing an element already initialized will give you the value you want.
Using above example:
struct c {
int a[5];
c() : a{1, a[0], 3, 4}{} // a[0] = 1
// a[1] = 1
// a[2] = 3
// a[3] = 4
// a[4] is not listed and will get 0.
};
According to cppreference.com:
The effects of aggregate initialization are:
Each array element or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.
Your code seems fine. However is somehow confusing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With