Karl M wrote:
Hi everyone,
I just notice some strange behaviors on the MS C++ compiler regarding
struct default constructor
You're just not used to the initialization rules for C++ (which are arcane
and obscure).
When you write...
int a[5];
....the contents of a[] are undefined.
Likewise...
struct Z
{
int a[5];
};
Z z;
....the contents of z are undefined.
8.5/9 of the C++ standard says
<quote>
If no initializer is specified for an object, and the object is of (possibly
cv-qualified) nonPOD class type (or array thereof), the object shall be
default-initialized; if the object is of const-qualified type, the
underlying class type shall have a user-declared default constructor.
Otherwise, if no initializer is specified for an object, the object and its
sub-objects, if any, have an indeterminate initial value; if the object or
any of its sub-objects are of const-qualified type, the program is
ill-formed.
</quote>
You're falling afoul of the "Otheriwse..." part of that quotation.
struct MyStruct
{
int a[5];
};
class MyClass
{
public:
MyClass();
~MyClass();
protected:
MyStruct m_MyStruct;
};
//#1:
MyClass::MyClass() //The default ctor for the class does not init the
struct with NULL(maybe there is no default ctor for struct yet?)
{
Here m_MyStruct has undefined content because MyStruct is a POD (which
implies no user defined constructors) so it's not initialized.
}
//#2 if I define the class ctor like this:
MyClass::MyClass() : m_MyStruct() //The default ctor for the class
does init the struct with NULL(call m_MyStruct() default ctor, now
there is one!) {
Correct. Since you've forced the creation of a default contructor for
MyStruct, that default constructor zero-fills the memory.
}
//#3 or like this:
MyClass::MyClass()
{
m_MyStruct = MyStruct(); // dose init the struct with NULL using a
local stack var init with NULL
Likewise, you've forced the creation (and calling) of a default constructor
for MyStruct() which zero-fills the memory.
}
//Now if I define the struct like this:
struct MyStruct
{
MyStruct()
{
int i;
for(i=0;i<5;i++)
a[i] = NULL;
}
int a[5];
};
This is equivalent to the default constructor that the compiler will
generate for you, so it shouldn't be surprising that the results are nearly
identical.
//#1 will init the struct with NULL because uses the defined struct
ctor but generate almost the same bin (asm) code as case #2 and #3
(the init stack var) without the struct ctor defined!
I guess I don't understand when the compiler knows about the struct
default constructor and when dose not (and expect for one defined).
It always knows about it, your example #1 simply doesn't force the compiler
to explicitly create a default constructor. Getting back to the quote from
8.5 of the standard - once you force a struct to have a constructor, it's no
longer a POD, so the code falls under the first sentence of that passage -
the object is default-initialized.
The best advice is: if you need initialization, write a constructor.
HTH
-cd