C++ Compiler behavior regerding struct constructors

K

Karl M

Hi everyone,
I just notice some strange behaviors on the MS C++ compiler regarding struct
default constructor, see the example bellow:
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?)
{
}
//#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!)
{
}
//#3 or like this:
MyClass::MyClass()
{
m_MyStruct = MyStruct(); // dose init the struct with NULL using a local
stack var init with NULL
}
//Now if I define the struct like this:
struct MyStruct
{
MyStruct()
{
int i;
for(i=0;i<5;i++)
a = NULL;
}
int a[5];
};
//#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).

Thank you
Karl M
 
C

Carl Daniel [VC++ MVP]

Karl said:
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 = 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
 
V

Vladimir Nesterovsky

C++ guarantees zero initialization for static variables of primitive type,
or of primitive structure, or of array of primitive types (structures) at
program start up.
Some heaps provide garantee for zero allocated memory.
Managed stack also provides zero initialized stack frame garantee.
In all other cases developer should take care of memory initialization.

I believe it's an extension that:

MyStruct m_MyStruct;

and

MyStruct m_MyStruct = MyStruct();

generate different code.
 
K

Karl M

Daniel,
Thank you for the insides of c++ standards.
I was only interseted if there is a way to call the "compiler default"
struct ctor in the class ctor body.
If I define a struct ctor then it is automatically embeded into the class
ctor underlying header (don't want that).

Regards,
Karl
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top