Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ struct default constructor behavior

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.

like image 858
jwchoi Avatar asked Apr 28 '14 07:04

jwchoi


People also ask

Can a struct have a default constructor?

C# does not allow a struct to declare a default, no-parameters, constructor. The reason for this constraint is to do with the fact that, unlike in C++, a C# struct is associated with value-type semantic and a value-type is not required to have a constructor.

Do default constructors have arguments?

Like all functions, a constructor can have default arguments. They are used to initialize member objects. If default values are supplied, the trailing arguments can be omitted in the expression list of the constructor.

Does default constructor initialize to zero?

For built-in types it results in zero-initialization.

Can a struct have a constructor C?

Cannot have a constructor inside a structure.


2 Answers

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).

like image 69
WhozCraig Avatar answered Sep 30 '22 17:09

WhozCraig


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. }

like image 27
Vlad from Moscow Avatar answered Sep 30 '22 17:09

Vlad from Moscow