Kamaal
Kamaal

Reputation: 61

Is there any difference between default built-in constructor and non-parameterized user-created default constructor?

Why does this work:

#include<iostream>

using namespace std;

class student{
    int rollNumber;
    int age;

public :
    student(){

    }
};

int main(){
    student const s;
}

But this does not work?

#include<iostream>

using namespace std;

class student{

    int rollNumber;
    int age;

};

int main(){
    student const s;
}

In both cases, there is a default constructor.

The top one has a user-defined default constructor, and the bottom one has the built-in default constructor.

Is there any difference between the default built-in constructor and a non-parameterized user-created default constructor?

In the second one, will the built-in default constructor be the same as the user-defined non-parameterized constructor?

Is there anyone who knows why this is happening?

Upvotes: 6

Views: 176

Answers (1)

Artyer
Artyer

Reputation: 40791

C++ has a concept of const-default-constructible types ([dcl.init.general]p8). It requires that if a const-qualified type T is default initialized, it must be const-default-constructible.

For classes, it must have a user-provided constructor, or every member must have a default member initializer or be const-default-constructible itself.

This is why the first example compiles (student(){} is user provided), and the second one fails (int rollNumber; and int age; don't have an initializer).

As for the why, the answer is "the standard says so". The rationale for this is given in [diff.dcl]p4:

A const object cannot be assigned to so it must be initialized to hold a useful value.

And it's been that way since C++98.

Though I agree that this seems like too strict of a restriction (What if all the members are mutable? What if you want to read the default member initializer of a single member, leaving the others uninitialized? What if you want to construct a dummy object to pass to something else with everything uninitialized?) In all cases though, you can do something like student _s; const student& s = _s; for basically the same effect.


This is one of the differences between the compiler provided default constructor and an explicit student() {}. A few more are:

  • The user provided one isn't trivial nor an aggregate (and this one wouldn't be usable in a constant expression)
  • noexcept-ness is automatically determined
  • The compiler provided one may be deleted
  • The user provided constructor explicitly will instantiate all the default constructors/member initializers of the members/bases in the body of the class (rather than when you attempt to use it)

And probably some more. These are the differences between user-provided and compiler generated constructors in general, being const-default-constructible seems to be the only one unique to default constructors.

Upvotes: 1

Related Questions