Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where in the Standard does it say that the default member initializer for U::j should be ignored by the compiler?

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;
};
like image 357
Ayrosa Avatar asked Nov 16 '16 13:11

Ayrosa


People also ask

What is a member initializer list?

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.

Why do we use initializer list in C++?

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.

How do you initialize a class member in C++?

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.

What is an initializer in C++?

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 };


2 Answers

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++.

like image 98
Jonathan Wakely Avatar answered Nov 15 '22 17:11

Jonathan Wakely


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.

like image 32
Fernando Marcos Avatar answered Nov 15 '22 17:11

Fernando Marcos