devxlogo

Change the Rules of C++ with Defaulted Functions

Change the Rules of C++ with Defaulted Functions

rogrammers have little control over the implicit declarations of the four canonical member functions. The compiler will not generate a default constructor for a class that has a user-declared copy-constructor. This frustrating state of affairs is about to change. The deleted and defaulted functions proposal provides a convenient mechanism for just this type of per-class customization. The following sections will show you how to use defaulted functions.


In certain cases, you need to define a default constructor manually, because the compiler will not implicitly-declare it. Not only is manual constructor definition tedious, it’s also not very efficient.


Use the new =default function specifier to make the compiler generate a member function that wouldn’t be generated otherwise.

Presenting the Problem
Suppose you’re designing a class that requires a user-defined copy constructor:

class C{public: C(const C& rhs);};

Later, when you try to create an object for this class, you get a compilation error:

C obj;//error: no default constructor exists for class CC * pc= new C; //same error

This kind of error can baffle even experienced programmers. Wasn’t the compiler supposed to implicitly declare a default constructor for class C? No, it wasn’t. When you declare a copy constructor in a class, the compiler doesn’t implicitly-declare a default constructor in that class. What if you want the compiler to generate a default constructor for you anyway? In C++03, there’s no way to override these language rules; you simply have to define the missing default constructor manually:

class C{public: C(const C& rhs); C() {} //manual definition of a default constructor};C obj; //OK

Not only is this tedious, the user-defined default constructor is often less efficient than the compiler’s implicitly-defined default constructor.

What a Difference a default Makes
C++09 offers a neat solution to this problem by extending the semantics to the keyword default. To force the compiler to generate a copy constructor for a class that wouldn’t normally get one, declare the default constructor like this:

class C{public: C(const C& rhs); C()=default;};

This way, the compiler will be forced to generate a default constructor for C.

Notice how elegantly this new feature extends the meaning of default, a keyword that already exists in C and C++. To make default‘s new role distinct from its traditional use in switch statements, defaulted functions now adopt pure virtual functions=specifier notation. The =default function specifier can be added to any of the special member functions?not just the constructor.

Author’s Note: By mere coincidence, the word default is used in both default constructors and defaulted functions. Recall that a default constructor is simply a constructor that can be invoked with no arguments. To avoid confusion, I use the phrase “defaulted constructor” to refer to a constructor that is declared with the =default specifier.

Destructors Unleashed
The C++ standard states clearly when the compiler will implicitly declare a destructor for a class and when it won’t. Here too, the rules don’t always meet your design goals. With the =default specifier you can override them.

Suppose you’re designing an interface for an asbtract pointing device:

struct Pointing_device_interface{ virtual bool onRightClick(Point xy)=0; virtual bool onDoubleClick(Point xy)=0; //.. virtual ~Pointing_device_interface();};

You must declare a virtual destructor for this class because otherwise, the compiler will implicitly declare a non-virtual destructor for it. Here’s the catch: after you declare a destructor (virtual or not), you must define it as well?even if it’s a dummy destructor:

Pointing_device_interface::~Pointing_device_interface(){}

In this example, you’re forced to manually define a dummy destructor simply because it must be virtual. As with the manual definition of a default constructor, a manual destructor?however trivial?is less efficient than an implicitly-defined one, and it imposes an unnecessary burden on the programmer. Ideally, you’d like to have the compiler generate a virtual destructor for you. Let’s see how C++09 defaulted functions get it done:

struct Pointing_device_interface{ virtual int onRightClick(Point xy)=0; virtual int onDoubleClick(Point xy)=0; //.. virtual ~Pointing_device_interface()=default;};

The compiler now implicitly defines a virtual destructor for Pointing_device_interface. The implicitly-defined destructor is as efficient as any implicitly-defined virtual destructor.

Remember, defaulted functions are only declared; you don’t define them. The compiler will automatically define them for you.

A Trivial Question
Defaulted functions solve two problems: they are more efficient than manual implementations and they free the programmer from the burden of defining those functions manually.

C++ makes a distinction between trivial and nontrivial special member functions. This distinction isn’t purely academic; a class that has one or more nontrivial special member functions isn’t a POD type. This raises another question: are defaulted functions trivial?

An inline defaulted function can be trivial. To qualify as trivial, a defaulted function must be identical to the function that the compiler would implicitly declare without the =default specifier. Additionally, the defaulted function must be inline. Consider:

struct S { inline S()=default;};

The defaulted constructor of S is trivial because the compiler would have implicitly-declared a trivial constructor for S by default:

struct S { //no user-declared canonical functions. Hence, S //has implicitly-declared trivial constructor, dtor etc.};

However, the following defaulted destructor isn’t trivial:

struct S { inline virtual ~S()=default;};

The defaulted destructor is inline, which is the first criterion for qualifying as trivial. However, this destructor is virtual, whereas the implicitly-declared destructor would have been non-virtual. Therefore, the defaulted destructor of S is not trivial.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist