Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

The C++ standard (section 8.5) says:

If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.

Why? I can't think of any reason why a user-provided constructor is required in this case.

struct B{   B():x(42){}   int doSomeStuff() const{return x;}   int x; };  struct A{   A(){}//other than "because the standard says so", why is this line required?    B b;//not required for this example, just to illustrate       //how this situation isn't totally useless };  int main(){   const A a; } 
like image 209
Karu Avatar asked Sep 14 '11 05:09

Karu


People also ask

Why is default constructor necessary?

What is the significance of the default constructor? They are used to create objects, which do not have any specific initial value. Is a default constructor automatically provided? If no constructors are explicitly declared in the class, a default constructor is provided automatically by the compiler.

Is a default constructor required?

For example, all members of class type, and their class-type members, must have a default constructor and destructors that are accessible. All data members of reference type and all const members must have a default member initializer.

What is the primary purpose of a default constructor C++?

Default Constructors in C++ They are primarily useful for providing initial values for variables of the class. The two main types of constructors are default constructors and parameterized constructors. Default constructors do not take any parameters.

Is default constructor automatically generated?

If any constructor is explicitly declared, then no default constructor is automatically generated. If a virtual destructor is explicitly declared, then no default destructor is automatically generated.


1 Answers

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:

  • http://www.ideone.com/h7TsA

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

  • http://www.ideone.com/SWk7B

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.

like image 75
Nawaz Avatar answered Oct 21 '22 11:10

Nawaz