C++11: defaulted and deleted functions

C++ programmers seem to (or at times have to) get along with the current syntax and semantics of the four special member functions since 1983, or so we think. However, library designers often come across stumbling blocks and annoyances that are a direct result of these rules.

By default, C++ implicitly declares the following four member functions for every class:

  • default constructor (ctor)
  • copy constructor (copy ctor)
  • operator = (assignment operator)
  • destructor (dtor)

In addition, a default global implementation of the following operators are implemented for each class:

  • address-of operator &
  • indirection operator *
  • member access operator ->
  • member indirection operator ->*
  • free-store allocation operator new
  • free-store deallocation operator delete

In both cases, users may override the defaults by providing an explicit declaration of these special member functions and operators in a given class. These default functions have been more trouble than use with most of the libraries, where you want control over how the object is allocated, copied or deleted.

The latest “Defaulted and Deleted Functions” proposal introduces two new syntactic mechanisms. The first mechanism reintroduces the default implementation of a member function or an operator. The second mechanism deletes the definition of the currently visible function.

default specifier

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class Sample
{
public:

    //  the pack of four functions that compiler
    //  implements by default for each class

    Sample() = default;
    Sample(const Sample&) = default;
    ~Sample() = default;
    Sample& operator=(const Sample&) = default;
};

Sample class declares all the four-special functions to be implemented by default. Actually we do not need to put default specifier with each method as compiler will provide you anyway but they are good way of documenting your code. default specifier can be applied to function definitions as well rather than declarations:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Sample
{
public:

    //  the pack of four functions that compiler
    //  implements by default for each class

    Sample();
    Sample(const Sample&) = default;
    virtual ~Sample();
    Sample& operator=(const Sample&) = default;
};

//  implementation file for Sample

Sample::Sample() = default;
Sample::~Sample() = default;

default specifier is not restricted to just member functions but can be used on free-standing functions as well. The only thing to remember is that not to specify default on both declaration and definition.

delete specifier

delete specifier is more interesting than default specifier, cause it can solve some of the annoying issues while writing general frameworks or libraries. One of the nice things is that it is declarative that you don’t want certain function to be implemented:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Sample
{
public:
    
    //  the pack of four functions that compiler
    //  implements by default for each class
    Sample() = default;
    virtual ~Sample() = default;
    
    //  I don't want objects of this class to be
    //  copied or assigned
    Sample(const Sample&) = delete;
    Sample& operator=(const Sample&) = delete;

    //  custom logic to copy objects of this class
    virtual Sample* Clone() const = 0;
};

Similar to default you can specify delete on definitions (with XCode, clang-llvm 3.0, I am running into some issues, but this should not be a problem moving forward.) in your implementation files.

Summary

I liked the idea that you can declaratively control the generation of special functions and operators for classes. This is big win as it will reduce the cryptic code and will document the intent very well. All in all this is very useful feature.

Defaulted and Deleted functions (open-std.org)