Let's say I have the following structure declaration (simple struct with no constructor).
struct Foo
{
int x;
int y;
int z;
char szData[DATA_SIZE];
};
Now let's say this struct is a member of a C++ class as follows:
class CFoobar
{
Foo _foo;
public:
CFoobar();
};
If I declare CFoobar's constructor as follows:
CFoobar::CFoobar()
{
printf("_foo = {%d, %d, %d}\n", _foo.x, _foo.y,_foo.z);
for (int x = 0; x < 100; x++)
printf("%d\n", _foo.szData[x]);
}
As you would expect, when CFoobar's constructor runs, garbage data gets printed out Obviously, the easy fix is to memset or ZeroMemory &_foo. It's what I've always done...
However, I did notice that if add _foo to the constructor's initialization list with no parameters as follows:
CFoobar::CFoobar()
: _foo()
{
That this appears to zero-out the member variables of _foo. At least that was the case with g++ on linux.
Now here's my question: Is this standard C++, or is this compiler specific behavior?
If it's standard behavior, can someone quote me a reference from an official source? Any "gotchas" in regards to implicit zero-init behavior with more complicated structs and classes?
If a structure variable has static storage, its members are implicitly initialized to zero of the appropriate type. If a structure variable has automatic storage, its members have no default initialization.
If T is scalar (arithmetic, pointer, enum), it is initialized from 0 ; if it's a class type, all base classes and data members are zero-initialized; if it's an array, each element is zero-initialized.
The most common benefit of doing this is improved performance. If the expression whatever is the same type as member variable x_, the result of the whatever expression is constructed directly inside x_ — the compiler does not make a separate copy of the object.
Yes, this is defined behaviour according to the standard. 12.6.2 [class.base.init] / 3 : "if the expression-list of the mem-initializer is omitted, the base class or member subobject is value-initialized."
Be warned, though, if Foo
wasn't a POD-type but still had no user-declared constructor (e.g. it had a std::string
type) then some very popular compilers would not correctly value-initialize it.
All compilers that I know of do correctly perform value-initialization of POD members when you use ()
as the initializer in a constructor initializer-list.
i find it hard to read the standard, but I found it I think:
To value-initialize an object of type T means:
if T is a non-union class type without a user-declared constructor, then every non-static data member and base- class component of T is value-initialized Value-initialization for such a class object may be implemented by zero-initializing the object and then calling the default constructor.
Section 8.5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With