Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Purpose of Explicit Default Constructors

I recently noticed a class in C++0x that calls for an explicit default constructor. However, I'm failing to come up with a scenario in which a default constructor can be called implicitly. It seems like a rather pointless specifier. I thought maybe it would disallow Class c; in favor of Class c = Class(); but that does not appear to be the case.

Some relevant quotes from the C++0x FCD, since it is easier for me to navigate [similar text exists in C++03, if not in the same places]

12.3.1.3 [class.conv.ctor]

A default constructor may be an explicit constructor; such a constructor will be used to perform default-initialization or value initialization (8.5).

It goes on to provide an example of an explicit default constructor, but it simply mimics the example I provided above.

8.5.6 [decl.init]

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

8.5.7 [decl.init]

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

In both cases, the standard calls for the default constructor to be called. But that is what would happen if the default constructor were non-explicit. For completeness sake:

8.5.11 [decl.init]

If no initializer is specified for an object, the object is default-initialized;

From what I can tell, this just leaves conversion from no data. Which doesn't make sense. The best I can come up with would be the following:

void function(Class c); int main() {   function(); //implicitly convert from no parameter to a single parameter } 

But obviously that isn't the way C++ handles default arguments. What else is there that would make explicit Class(); behave differently from Class();?

The specific example that generated this question was std::function [20.8.14.2 func.wrap.func]. It requires several converting constructors, none of which are marked explicit, but the default constructor is.

like image 406
Dennis Zickefoose Avatar asked May 14 '10 19:05

Dennis Zickefoose


People also ask

Why do we use explicit constructor?

The explicit function specifier controls unwanted implicit type conversions. It can only be used in declarations of constructors within a class declaration. For example, except for the default constructor, the constructors in the following class are conversion constructors.

Can we call default constructor explicitly?

Yes, it is possible to call special member functions explicitly by the programmer.

What does a default constructor do?

A default constructor is a constructor that either has no parameters, or if it has parameters, all the parameters have default values. If no user-defined constructor exists for a class A and one is needed, the compiler implicitly declares a default parameterless constructor A::A() .


1 Answers

This declares an explicit default constructor:

struct A {   explicit A(int a1 = 0); };  A a = 0; /* not allowed */ A b; /* allowed */ A c(0); /* allowed */ 

In case there is no parameter, like in the following example, the explicit is redundant.

struct A {   /* explicit is redundant. */   explicit A(); }; 

In some C++0x draft (I believe it was n3035), it made a difference in the following way:

A a = {}; /* error! */ A b{}; /* alright */  void function(A a); void f() { function({}); /* error! */ } 

But in the FCD, they changed this (though, I suspect that they didn't have this particular reason in mind) in that all three cases value-initialize the respective object. Value-initialization doesn't do the overload-resolution dance and thus won't fail on explicit constructors.

like image 200
Johannes Schaub - litb Avatar answered Oct 03 '22 17:10

Johannes Schaub - litb