How it works...

A class has several special members that can be implemented, by default, by the compiler. These are the default constructor, copy constructor, move constructor, copy assignment, move assignment, and destructor. If you don't implement them, then the compiler does it so that instances of a class can be created, moved, copied, and destructed. However, if you explicitly provide one or more of these special methods, then the compiler will not generate the others according to the following rules:

  • If a user-defined constructor exists, the default constructor is not generated by default.
  • If a user-defined virtual destructor exists, the default constructor is not generated by default.
  • If a user-defined move constructor or move assignment operator exists, then the copy constructor and copy assignment operator are not generated by default.
  • If a user-defined copy constructor, move constructor, copy assignment operator, move assignment operator, or destructor exists, then the move constructor and move assignment operator are not generated by default.
  • If a user-defined copy constructor or destructor exists, then the copy assignment operator is generated by default.
  • If a user-defined copy assignment operator or destructor exists, then the copy constructor is generated by default.
Note that the last two rules in the preceding list are deprecated rules and may no longer be supported by your compiler.

Sometimes, developers need to provide empty implementations of these special members or hide them in order to prevent the instances of the class from being constructed in a specific manner. A typical example is a class that is not supposed to be copyable. The classical pattern for this is to provide a default constructor and hide the copy constructor and copy assignment operators. While this works, the explicitly defined default constructor ensures the class is no longer considered trivial and, therefore, a POD type. The modern alternative to this is using a deleted function as shown in the preceding section.

When the compiler encounters =default in the definition of a function, it will provide the default implementation. The rules for special member functions mentioned earlier still apply. Functions can be declared =default outside the body of a class if and only if they are inlined:

    class foo 
{
public:
foo() = default;

inline foo& operator=(foo const &);
};

inline foo& foo::operator=(foo const &) = default;

When the compiler encounters the =delete in the definition of a function, it will prevent the calling of the function. However, the function is still considered during overload resolution, and only if the deleted function is the best match, the compiler generates an error. For example, by giving the previously defined overloads for the run() function, only calls with long integers are possible. Calls with arguments of any other type, including int, for which an automatic type promotion to long exists, will determine a deleted overload to be considered the best match and therefore the compiler will generate an error:

    run(42);  // error, matches a deleted overload 
run(42L); // OK, long integer arguments are allowed

Note that previously declared functions cannot be deleted, as the =delete definition must be the first declaration in a translation unit:

    void forward_declared_function(); 
// ...
void forward_declared_function() = delete; // error
The rule of thumb (also known as The Rule of Five) for class special member functions is that, if you explicitly define any copy constructor, move constructor, copy assignment operator, move assignment operator, or destructor, then you must either explicitly define or default all of them.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset