6

As I know, if the programmer doesn't implement any constructor, the compiler automatically generates default constructor that does nothing. I think it works for struct as well.

I used this with inheritance.

struct Parent {
    int a;
};

struct Child : Parent {
    int b;
    Child () {
        printf("child constructor\n");
    }
}

int main () {
    Child c;
    printf("%d\n", c.a);        // c.a = dummy value
    printf("%d\n", c.b);        // c.b = 0
    return 0;
}

In the above code, c.a was dummy value. However, when I change the Child constructor, it was zero. The only difference is that the Child explicitly calls parent's constructor in its constructor.

struct Parent {
    int a;
};

struct Child : Parent {
    int b;
    Child () : Parent () {
        printf("child constructor\n");
    }
}

int main () {
    Child c;
    printf("%d\n", c.a);        // c.a = 0
    printf("%d\n", c.b);        // c.b = 0
    return 0;
}

What happens? I spend some time but cannot find any reason. The compiler I used is VS2008. Thank you in advance.

jwchoi
  • 607
  • 7
  • 13
  • The question seems to be related to this question: http://stackoverflow.com/questions/8280023/does-a-c-struct-have-a-default-constructor – Codor Apr 28 '14 at 07:16

2 Answers2

9

Parent is a POD-type (plain old data type). It has no constructors or destructors (besides the implicit, which are trivial), complex members, etc. Its just a struct with scalars or other POD-type members. When you do this:

struct Child : Parent 
{
    int b;
    Child () {
        printf("child constructor\n");
    }
}

you're simply constructing the child object. No relevant construction of Parent is taking place. The base type undergoes default initialization:

C++11 § 8.5,p11

If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value. [ Note: Objects with static or thread storage duration are zero-initialized, see 3.6.2.

For your POD-type, this means:

C++11 § 8.5,p6

To default-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type (Clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);

  • if T is an array type, each element is default-initialized;

  • otherwise, no initialization is performed.

But when you do this:

struct Child : Parent 
{
    int b;
    Child () : Parent () {
        printf("child constructor\n");
    }
}

something different happens: You're invoking value-initialization of the Parent base type. due to the ().

C++11 § 8.5,p10

An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.

For POD-types (of which Parent is one) value-initialization will eventually zero-initialize the members.

C++11 § 8.5,p7

To value-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);

  • if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.

  • if T is an array type, then each element is value-initialized;

  • otherwise, the object is zero-initialized.

Thus a is zero in the second case, but not in the first. (well, it could be zero in the first, you can't really say; its value is indeterminate until you assign something to it).

Community
  • 1
  • 1
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • PODs have constructors, too. – Sebastian Mach Apr 28 '14 at 07:37
  • @phresnel if you're referring to the implicit trivial constructors, they're noted; otherwise kindly elaborate. – WhozCraig Apr 28 '14 at 07:40
  • @phresnel its a tricky part of the standard, so I'm never surprised when I get something wrong (likely did here too, wouldn't be surprised), so if I seemed a little anxious in that retort it wasn't intentional. Thanks for keeping me honest =P – WhozCraig Apr 28 '14 at 07:51
  • But I did nothing except falsely accusing you of something :D – Sebastian Mach Apr 28 '14 at 07:55
  • @phresnel no, actually, i look at that phrasing now and it isn't exactly crystal clear, it could imply only the destructors are trivial. I'll address it. No worries. Edit: much better. thanks. – WhozCraig Apr 28 '14 at 07:57
  • We.. we.. welcome, I guess (but I know such situations, too :D) – Sebastian Mach Apr 28 '14 at 08:03
2

According to the C++ STandard

11 An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.

and

8 To value-initialize an object of type T means: — if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized

So in code snippet

struct Parent {
    int a;
};

struct Child : Parent {
    int b;
    Child () : Parent () {
        printf("child constructor\n");
    }

class Parent is zero initialized. Its members of scalar types that is data member a is zero initialized. }

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335