Here is a related C answer that doesn\'t work (as a zero initializer for a struct) on C++: Initializing a struct to 0. One of the solutions presented is this:
Generically it's not possible. A class may not provide a way to access all members and in those cases the best you can do is value initialize it which will give you a default version of that class.
Objects in C++ are given the ability to control the values of any subobjects within them. As such, C++ has no mechanism that will force zero-initialization onto any object in general.
Objects with no user-provided constructors or default member initializers can undergo zero-initialization in two cases: if the variable is declared static
, or if the object is being value-initialized. There are multiple syntaxes that will provoke value initialization of an object, including T()
, T{}
, and T t = {};
, where applicable.
But other than that, if the creator of the type of an object does not want it to be zero-initialized, then you cannot impose that upon the object. You can ask for value-initialization or default-initialization, but whether either of these will invoke zero-initialization depends on the type.
I figured it out: to get it to compile, just delete the zero:
myStruct _m1 = {};
It now compiles. However, I ran a bunch of tests to check some things, and this does NOT initialize all elements of the struct to zero! Rather, it initializes the struct to its default values.
Assuming you have this struct:
typedef struct
{
int num1 = 100;
int num2 = -100;
int num3;
int num4 = 150;
} data_t;
Note: the typedef
above is a carry-over from when I was testing this stuff in C instead of C++ (although the default struct values are not allowed in C, of course). For C++, this is preferred instead:
struct data_t
{
int num1 = 100;
int num2 = -100;
int num3;
int num4 = 150;
};
So please ignore it wherever I unnecessarily use typedef
to define the structs below.
Anyway, if I declare one of the above data_t
structs, and then do this:
data_t d2 = {};
printf("d2.num1 = %i\nd2.num2 = %i\nd2.num3 = %i\nd2.num4 = %i\n\n",
d2.num1, d2.num2, d2.num3, d2.num4);
...the output will be:
d2.num1 = 100
d2.num2 = -100
d2.num3 = 0
d2.num4 = 150
And I'm not even sure if d2.num3
is zero because it was initialized to zero or because it was left uninitialized, and that memory location happened to contain zero.
As explained here: https://en.cppreference.com/w/cpp/language/zero_initialization, you can also do this:
myStruct _m1{};
In the example above, this code:
data_t d2{};
printf("d2.num1 = %i\nd2.num2 = %i\nd2.num3 = %i\nd2.num4 = %i\n\n",
d2.num1, d2.num2, d2.num3, d2.num4);
...would produce output identical to what I showed above.
Even in cases where setting the struct to = {0}
DOES work, such as this:
// Does NOT do what I expected! Only sets the FIRST value in the struct to zero!
// The rest seem to use default values.
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 still not what I expected, as it only sets the first value to zero! (I don't understand why):
d3.num1 = 0
d3.num2 = -100
d3.num3 = 0
d3.num4 = 150
On C-style arrays, however (NOT structs), these semantics work fine. Refer to this answer here (How to initialize all members of an array to the same value?). The following lines, therefore, both set all elements of the C-style array to zero when using C++:
uint8_t buffer[100] = {0}; // sets all elements to 0 in C OR C++
uint8_t buffer[100] = {}; // sets all elements to 0 in C++ only (won't compile in C)
So, after much experimentation, it looks like the following several ways are the ONLY ways to zero-initialize a struct, PERIOD. If you know differently, please comment and/or leave your own answer here.
Be explicit:
// C-style typedef'ed struct
typedef struct
{
int num1 = 100;
int num2 = -100;
int num3;
int num4 = 150;
} data_t;
// EXPLICITLY set every value to what you want!
data_t d1 = {0, 0, 0, 0};
// OR (using gcc or C++20 only)
data_t d2 = {.num1 = 0, .num2 = 0, .num3 = 0, .num4 = 0}
Use memset()
to force all bytes to zero:
data_t d3;
memset(&d3, 0, sizeof(d3));
Set all default values to zero in the first place:
// C-style typedef'ed struct
typedef struct
{
int num1 = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
} data_t;
// Set all values to their defaults, which are zero in
// this case
data_t d4 = {};
// OR
data_t d5{}; // same thing as above in C++
// Set the FIRST value only to zero, and all the rest
// to their defaults, which are also zero in this case
data_t d6 = {0};
Write a constructor for the C++ struct
// 1. Using an initializer list
struct data
{
int num1;
int num2;
int num3;
int num4;
data() :
num1(0),
num2(0),
num3(0),
num4(0) {}
};
data d7; // all values are zero
// OR: 2. manually setting the values inside the constructor
struct data
{
int num1;
int num2;
int num3;
int num4;
data()
{
num1 = 0;
num2 = 0;
num3 = 0;
num4 = 0;
}
};
data d8; // all values are zero
Use a struct with no default values, and make your object you create from it static
tpedef struct
{
int num1;
int num2;
int num3;
int num4;
} data_t;
// `static` forces a default initialization of zero for each
// value when no other default values are set
static data_t d9;
So, if you have a struct with non-zero default values, and you want to zero all values, you must do it EXPLICITLY! Here are some more ways:
// 1. Have a `constexpr` copy of the struct that you use to
// reset other struct objects. Ex:
struct data
{
int num1 = 1;
int num2 = 7;
int num3 = -10;
int num4 = 55;
};
constexpr data DATA_ALL_ZEROS = {0, 0, 0, 0};
// Now initialize d13 to all zeros using the above `constexpr` struct
// object
data d13 = DATA_ALL_ZEROS;
// OR 2. Use a `zero()` member function to zero the values:
struct data
{
int num1 = 1;
int num2 = 7;
int num3 = -10;
int num4 = 55;
zero()
{
num1 = 0;
num2 = 0;
num3 = 0;
num4 = 0;
}
};
data d14;
d14.zero();
data_t d{}
, data_t d = {}
, and data_t d = {0}
, actually set all members of a struct to zero!data_t d{}
sets all values to their defaults defined in the struct.data_t d = {}
also sets all values to their defaults.data_t d = {0}
sets only the FIRST value to zero, and all other values to their defaults.SO, BE EXPLICIT!
Note that the above key take-aways I wrote seem to contradict this documentation, so it has led me to ask this follow-up question, listed as Reference #1 below, which has proven VERY helpful to my understanding!
cpp/run_struct_initialization.sh