Home > Articles > Programming > C/C++

C++ Reference Guide

Hosted by

Constructors FAQ, Part I

Last updated Jan 1, 2003.

A detailed account of standard C++ rules regarding constructors and the rest of the so-called special member functions is available here since the early days of the C++ Reference Guide. However, the number of questions about constructors on various C++ forums and emails that I receive recently suggests that this topic is still very confusing and surrounded by myths. Therefore, I believe that a supplementary column in the form of frequently-asked questions will dispel those myths and misunderstandings.

Question: What is a default constructor?

Answer: Many programmers believe that a default constructor is a constructor that the compiler automatically generates when the user doesn’t define a constructor. This isn’t correct. A default constructor can be user-defined or compiler-generated; it’s a default constructor if and only if it can be invoked without any arguments. The following classes all have default constructors:

struct A
{
int x;
A(): x(0) {}
};
struct B: A
{
//no user-defined ctor.
//the compiler implicitly declares a default constructor
};
class C
{
public:
explicit C(int n=0, int m=0); // may be invoked with no arguments
};
C c0, c2(9,0);

As class C demonstrates, the default constructor needn’t be declared with an empty parameter list; C’s constructor qualifies as a default constructor because it may be invoked with no arguments.

Question: When does the compiler implicitly declare a default constructor?

Answer: The compiler will implicitly declare a default constructor for any class that doesn’t declare any constructor explicitly, provided that the class in question doesn’t contain any reference or const data members. Notice that if the user declares a copy constructor, that constructor will preclude the compiler’s implicit declaration of a default constructor. Consider:

class A
{
 int x;
public:
 void f();
};//no user declared constructors of any kind; 
A a; //OK, using implicitly-declared default ctor

The compiler implicitly declares a default constructor, copy constructor (as well as an assignment operator and a destructor which I will not discuss here) for class A because the implementer of this class didn’t declare any constructor for it. Let’s examine this issue more closely. Suppose the user adds the following copy constructor declaration:

class A2
{
 int x;
public:
 A2(const A2&); //the access type doesn’t matter, it could be private or protected too
void f();
}; 

The compiler doesn’t declare an implicit default constructor for class A2 because the user has already declared a constructor. Even if the user-declared constructor is a copy constructor or a constructor taking multiple arguments, that’s enough to preclude the implicit declaration of a default constructor! This means that A2 doesn’t have a default constructor at all:

A2 a2; //error, A2 has no default constructor 

As an aside, you can’t even use the copy-constructor to instantiate an object of type A2 because you can’t instantiate the argument for the copy constructor:

A2 a3(a2); //a2 cannot be instantiated because no default ctor is available

Question: What does the implicitly declared default constructor do?

Answer: Here’s another common myth -- many believe that the implicitly-declared default constructor does secret initialization operations behind their back, or that it allocates memory for the object. This is sheer nonsense. The implicitly-declared constructor does absolutely nothing! Remember: declaring a constructor -- either explicitly or implicitly -- doesn’t necessarily mean that the constructor is also defined. The following examples demonstrate the difference between a constructor declaration and its definition:

class B
{
 B(); //declaration only
};
B::B() {} //separate definition of the user-declared default constructor

class C
{
C() {} //declaration and definition
};
class D
{
//implicit declaration of a default constructor, no implicit definition
};
class E
{
//implicit declaration + implicit definition of a default constructor
virtual void f();
};
class F
{
virtual void f();
public:
F(); ////explicit declaration a default constructor, user forgot a definition
};

In the last example, the lack of a definition for F’s default constructor is most likely a programmer’s omission. This type of a human error will cause a linkage error when you try to instantiate this class:

F f; //linkage error: symbol ’F::F()’ could not be resolved

To conclude, a user-declared constructor is never implicitly-defined. If the user has declared a constructor, he or she is responsible for defining it as well, unless they intentionally left it unimplemented (to prevent object copying for instance). By contrast, an implicitly-declared constructor may be implicitly-defined under certain conditions which I will explain in the second part of this series.

The second part of this series will also answer additional questions including: When does the compiler implicitly define a default constructor? Is it true that the implicitly-defined constructor allocate memory for its object? Does the implicitly-defined constructor initialize the object’s data members?