Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are my struct's members not properly initialised using `{}`? [duplicate]

I had the following code:

#include <iostream>

struct T
{
   int a, b, c;
};

int main()
{
   T t = {0};
   std::cout << t.a << ',' << t.b << ',' << t.c << '\n';
}

Output:

0,0,0

After many years of this code running happily in a critical production environment, serving a vital function, the requirements of the project changed and I needed the output to be 1,1,1.

So, I changed {0} to {1}:

#include <iostream>

struct T
{
   int a, b, c;
};

int main()
{
   T t = {1};
   std::cout << t.a << ',' << t.b << ',' << t.c << '\n';
}

Output:

1,0,0

I expected 1,1,1 instead.

Why are my struct's members not all being initialised properly?

like image 388
Lightness Races in Orbit Avatar asked Feb 10 '13 12:02

Lightness Races in Orbit


People also ask

Why can't we initialise members of structure at the time of declaration?

The direct answer is because the structure definition declares a type and not a variable that can be initialized. Your example is: struct s { int i=10; }; This does not declare any variable - it defines a type.

Can we initialize the data members of structure?

Structure members cannot be initialized with declaration.

How do you initialize a new struct?

A non POD struct may as well have a constructor so it can initialize members. If your struct is a POD then you can use an initializer. Alternatively you can use the default constructor. C c = C(); // Zero initialize using default constructor C c{}; // Latest versions accept this syntax.

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

// In C++ We can Initialize the Variables with Declaration in Structure. Structure members can be initialized using curly braces '{}'. For example, following is a valid initialization.


1 Answers

When you write = {0}, that only explicitly initialises the first member; the rest are zero-initialised implicitly according to the standard, so it appears at first glance that you explicitly initialised all members with the 0 that you wrote, but you didn't.

That place where you wrote 0 only affects the first member. So when, one day, you changed it to 1 thinking that it'll change all members, you'll have a bug, like here. It's misleading/dangerous/silly/fragile code.

For that reason, without an accompanying explanatory comment, = {0} will not pass code review in my team. You should originally have written:

T t = {};

And now, to solve your problem according to the new requirements, you should write:

T t = {1,1,1};

or, if you don't mind your struct potentially losing POD-ness, give T a constructor.


Formal wording

[C++11: 8.5.1/2]: When an aggregate is initialized by an initializer list, as specified in 8.5.4, the elements of the initializer list are taken as initializers for the members of the aggregate, in increasing subscript or member order. Each member is copy-initialized from the corresponding initializer-clause. If the initializer-clause is an expression and a narrowing conversion (8.5.4) is required to convert the expression, the program is ill-formed. [..]

[C++11: 8.5.1/6]: An initializer-list is ill-formed if the number of initializer-clauses exceeds the number of members or elements to initialize.

[C++11: 8.5.1/7]: If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from an empty initializer list (8.5.4).

like image 57
Lightness Races in Orbit Avatar answered Oct 14 '22 08:10

Lightness Races in Orbit