Why does C++ require a user-provided default constructor to default-construct a const object?

The reason is that if the class doesn’t have a user-defined constructor, then it can be POD, and the POD class is not initialized by default. So if you declare a const object of POD which is uninitialized, what use of it? So I think the Standard enforces this rule so that the object can actually be useful.

struct POD
{
  int i;
};

POD p1; //uninitialized - but don't worry we can assign some value later on!
p1.i = 10; //assign some value later on!

POD p2 = POD(); //initialized

const POD p3 = POD(); //initialized 

const POD p4; //uninitialized  - error - as we cannot change it later on!

But if you make the class a non-POD:

struct nonPOD_A
{
    nonPOD_A() {} //this makes non-POD
};

nonPOD_A a1; //initialized 
const nonPOD_A a2; //initialized 

Note the difference between POD and non-POD.

User-defined constructor is one way to make the class non-POD. There are several ways you can do that.

struct nonPOD_B
{
    virtual void f() {} //virtual function make it non-POD
};

nonPOD_B b1; //initialized 
const nonPOD_B b2; //initialized 

Notice nonPOD_B doesn’t defined user-defined constructor. Compile it. It will compile:

And comment the virtual function, then it gives error, as expected:


Well, I think, you misunderstood the passage. It first says this (§8.5/9):

If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; […]

It talks about non-POD class possibly cv-qualified type. That is, the non-POD object shall be default-initialized if there is no initializer specified. And what is default-initialized? For non-POD, the spec says (§8.5/5),

To default-initialize an object of type T means:
— if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);

It simply talks about default constructor of T, whether its user-defined or compiler-generated is irrelevant.

If you’re clear up to this, then understand what the spec next says ((§8.5/9),

[…]; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor.

So this text implies, the program will be ill-formed if the object is of const-qualified POD type, and there is no initializer specified (because POD are not default initialized):

POD p1; //uninitialized - can be useful - hence allowed
const POD p2; //uninitialized - never useful  - hence not allowed - error

By the way, this compiles fine, because its non-POD, and can be default-initialized.

Leave a Comment