Is there any difference between struct Data d = {0} and struct Data d = {}
Asked Answered
F

4

7

I have two types of structure variable initialization in my code.

Example

#include<iostream>
#include<string>
using namespace std;
struct Data{
   int arr[5];
   float x;

};
int main(){
   struct Data d = {0};
   struct Data d1 = {};
   cout<<d.arr[0]<<d.x;
   cout<<d1.arr[0]<<d1.x<<endl;
   return 0;
}

I am running the code ad getting 0 0 0 0 as my output. Please help me, is there any difference between both initialization.

Faulk answered 23/11, 2016 at 6:2 Comment(4)
One is an initialization list that that you have equal to the other is just an empty initialization list.Pressor
And what did you expect to have inside each? You shouldn't initialize your struct like that. You need to access each thing inside your struct and initialize it. Probably have a function that takes in a struct and has a for loop that initializes everything in your array to 0 and your x to 0Pressor
@Danh don't be a jerk. tagging a question as c because it involves syntax common to c and c++ is incorrect but it's not "spamming."Latashialatch
Possible duplicate of Proper way to initialize C++ structsToothache
A
7

According to the rule of aggregate initialization, the effect is the same here, i.e. all the members of the struct will be value-initialized (zero-initialized here for non-class types).

If the number of initializer clauses is less than the number of members and bases (since C++17) or initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default initializers, if provided in the class definition, and otherwise (since C++14) by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.

More precisely,

struct Data d = {0}; // initialize the 1st member of Data to 0, value-initialize(zero-initialize) the remaining members
struct Data d1 = {}; // value-initialize(zero-initialize) all the members of Data

Note that the whole story is based on that Data is an aggregate type and its members are non-class types, otherwise the behavior would change according to the rule of list initialization.

Agribusiness answered 23/11, 2016 at 6:9 Comment(2)
I think it's worth to mention the effect when Data have constructorWarford
Also there would be a difference if the first member of Data was a class typeChick
I
0

The default initialization using {} is defined as initialization of each member by using {}. So, by doing

struct Data d1 = {};

Data d1 is initialized to {{},{}}, which is {{0, 0, 0, 0, 0}, 0.0},

as 0 and 0.0 are default values for int and float resp.

This is the reason you don't see any difference. Both of them invariably do the same thing in your case.

Differences lie in these cases:

1.) This is when providing initializer inside {} becomes mandatory:

struct X {
    X(int);
};

X  x1 {};    // error : empty initializer. X(int) states that an int is required to construct an X.
X  x2 {0};   // OK

2.) Scenario when zero initialization is forbidden:

struct Test {
    string name;
    int year;
};
Test alpha0{0}; // Error. Because name in Test fails at zero-initialization.
Test alpha{};     // OK. Because name in Test is default-initialized with empty string "".
Inapprehensible answered 23/11, 2016 at 6:25 Comment(0)
Z
0

The result is the same in this case, but not necessarily so in other cases.

In this case, you haven't provided a ctor, so you're using aggregate initialization. This gives zero-initialization for the empty-init-list, and you're supplying 0 for the non-empty one, so the two work out the same.

If you provided a ctor, it would be trivial to get different results from the two:

#include <iostream>

struct foo {
    int f;

    foo(int f = 5) : f(f) {}
    friend std::ostream &operator<<(std::ostream &os, foo const &f) { 
        return os << f.f;
    }
};

int main() { 

    foo f1{};
    foo f2{0};

    std::cout << "Empty init list: " << f1 << "\n";
    std::cout << "zero init list: " << f2 << "\n";
}

Although a ctor is the most obvious way to do this, it's not the only one. For another obvious example (C++11 and newer only):

struct foo { 
    int f = 5;
};
Zygapophysis answered 23/11, 2016 at 6:26 Comment(0)
O
-2

Yes, there is a difference. In the first case you're explicitly initializing the first member of Data (arr[0]) to zero. In the second case you aren't initializing anything and simply reading whatever value happens to be there. In this case it was also zero, but that's not guaranteed to work, especially in a more complicated program.

It's always a good idea to initialize all the members of a struct. Consider this slightly modified version of your program which should make what's happening clear:

#include<iostream>
#include<string>
using namespace std;
struct Data{
   int arr[5];
   float x;
};
int main(){
   struct Data d = {1, 2, 3, 4, 5, 3.14f};
   struct Data d1 = {};
   cout<<d.arr[0]<<", "<<d.x<<", ";
   cout<<d1.arr[0]<<", "<<d1.x<<endl;
   return 0;
}

This will print:

1, 3.14, 0, 0
Omasum answered 23/11, 2016 at 6:19 Comment(1)
What is your program supposed to illustrate?Chick

© 2022 - 2024 — McMap. All rights reserved.