c++structinitializationzero-initialization

Why doesn't initializing a C++ struct to `= {0}` set all of its members to 0?


After doing a ton of testing and writing this answer on how to initialize a struct to zero in C++ (note: the downvote on it was before my total rewrite of it), I can't understand why = {0} doesn't set all members of the struct to zero!

If you do this:

struct data_t
{
    int num1 = 100;
    int num2 = -100;
    int num3;
    int num4 = 150;
};

data_t d3 = {0};
printf("d3.num1 = %i\nd3.num2 = %i\nd3.num3 = %i\nd3.num4 = %i\n\n",
       d3.num1, d3.num2, d3.num3, d3.num4);

...the output is:

d3.num1 = 0
d3.num2 = -100
d3.num3 = 0
d3.num4 = 150

...although I expected the output to be this:

d3.num1 = 0
d3.num2 = 0
d3.num3 = 0
d3.num4 = 0

...which means that only the FIRST member was set to zero, and all the rest were set to their defaults.

I was always under the impression that initializing a struct in any of these 3 ways would zero-initialize it, but obviously I'm wrong!

  1. data_t d{}
  2. data_t d = {}
  3. data_t d = {0}

My key takeaway from this answer is therefore this:

The big take-away here is that NONE of these: data_t d{}, data_t d = {}, and data_t d = {0}, actually set all members of a struct to zero!

  1. data_t d{} sets all values to their defaults defined in the struct.
  2. data_t d = {} also sets all values to their defaults.
  3. And data_t d = {0} sets only the FIRST value to zero, and all other values to their defaults.

So, why doesn't initializing a C++ struct to = {0} set all of its members to 0?

Note that my key take-aways above actually contradict this rather official-looking documentation I've been using for years (https://en.cppreference.com/w/cpp/language/zero_initialization), which says that T t = {} ; and T {} ; are both zero initializers, when in fact, according to my tests and take-away above, they are NOT.

References:

  1. How to initialize a struct to 0 in C++
  2. Update: I was just pointed to this reference too: What does {0} mean when initializing an object?

Solution

  • So, why doesn't initializing a C++ struct to = {0} set all of its members to 0?

    Because you are only providing one value, while the class has more than one member.

    When you have T t{}; or T t = {} what you are doing is called value initialization. In value initialization, if the object/member does not have a default constructor, or a default member initializer, then the compiler falls back to zero initializing the objec/member. So with

    data_t d{}
    

    the value of the members in order would be 100, -100, 0 ,150 and that 0 for num3 happens because it has no default and you did not provide a value in the {} so the compiler falls back to zero initializing num3. This is the same with data_t d = {}. With data_t d = {0} you provide the first element, so num1 is 0, but then like the first two, all of the other members are initialized with their default value if they have one, or zero initialized if they don't, giving you 0, -100, 0, 150 for the member values.

    This was a change that happened when C++11 was released and allowed for default member initializers.


    If your data_t was defined like

    typedef struct
    {
        int num1;
        int num2;
        int num3;
        int num4;
    } data_t;
    

    then data_t d{}, data_t d = {}, data_t d = {0} would all leave you with a zero initialized class since there are no default member initializers and the only value you provide in you braced-init-list (the technical name for {...}) is zero so all members become zero.