Consider the following snippet:
#include <iostream>
union U{
U(): i(1) {}
int i;
int j = 2; // this default member initializer is ignored by the compiler
};
U u;
int main(){
std::cout << u.i << '\n';
std::cout << u.j << '\n';
}
The code prints (see live example):
1
1
Where in the Standard does it say that the default member initializer for the member U::j
is ignored by the compiler?
Note that the union below doesn't compile and this is OK according to [class.union.anon]/4. I was thus expecting the snippet above also not to compile.
See live example:
union U{
int i = 1;
int j = 2;
};
Member initializer list is the place where non-default initialization of these objects can be specified. For bases and non-static data members that cannot be default-initialized, such as members of reference and const-qualified types, member initializers must be specified.
When do we use Initializer List in C++? Initializer List is used in initializing the data members of a class. The list of members to be initialized is indicated with constructor as a comma-separated list followed by a colon. Following is an example that uses the initializer list to initialize x and y of Point class.
There are two ways to initialize a class object: Using a parenthesized expression list. The compiler calls the constructor of the class using this list as the constructor's argument list. Using a single initialization value and the = operator.
An initializer specifies the initial value of a variable. You can initialize variables in these contexts: In the definition of a variable: C++ Copy. int i = 3; Point p1{ 1, 2 };
Where in the Standard does it say that the default member initializer for the member U::j is ignored by the compiler?
See [class.base.init] paragraph 9 bullet 9.1 in the C++17 CD.
N.B. your demo has undefined behaviour, because the active member of the union is i
but you read from j
. This works with some compilers as a non-standard extension, but is not allowed in ISO C++.
Note that you are declaring a union object, where all members share the same memory area - member variables turn into different "typed views" of the same data.
Thus, as members i and j are effectively stored in the same memory location, any initialization you perform on j (with the initializer) will be overwritten by your constructor setting i.
Just for test, remove the initialization of i from the constructor:
#include <iostream>
union U{
U() {}
int i;
int j = 2; // this initializes both i & j
};
U u;
int main(){
std::cout << u.i << '\n';
std::cout << u.j << '\n';
}
The output would be
2
2
Update: As per @Ayrosa comments and being just intrigued, I modified the original snippet to perform some initialization with a function (instead of a constant) to induce side effects.
#include <iostream>
int static someStatic()
{
std::cout << "Initializer was not ignored\n";
return(2);
}
union U{
U(): i(1) {}
int i;
int j = someStatic(); // this default member initializer is ignored by the compiler
};
U u;
int main(){
std::cout << u.i << '\n';
std::cout << u.j << '\n';
}
Result was:
1
1
Meaning that the call to someStatic()
was, in fact, ignored by the compiler.
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