V832. It's better to use '= default;' syntax instead of empty body.
If special functions are declared with '= default', a class can be trivially copied. This might help to copy and initialize such a class in a more optimized way.
Rules for forming special functions are complicated. Therefore, when writing classes/structures it's best to explicitly define some of them for better understanding of code. Here are examples of such special functions: default constructor, copy constructor, copy operator, destructor, move constructor, move operator.
struct MyClass
{
int x;
int y;
MyClass() {}
~MyClass() {}
};
or this way:
// header
struct MyClass
{
int x;
int y;
};
// cpp-file
MyClass::MyClass() {}
MyClass::~MyClass() {}
In the example, we see a default constructor and destructor. A developer defines such functions with an empty body. However, this way a class can become nontrivially copied. Due to this, the compiler will not always be able to generate more optimized code. Therefore, C++11 introduces '= default' for special functions.
struct MyClass
{
int x;
int y;
MyClass() = default;
~MyClass() = default;
};
The compiler will generate both bodies of special functions and deduce 'constexpr' and 'noexcept' specifiers for them automatically.
Note that when you move special functions from the class body, the compiler considers them user-defined. This might lead to pessimization, so it's best to add '= default' directly in the class body if possible.
You will not get the warning if:
- the standard used is below C++11;
- the constructor has an initialization list;
- the class does not contain non-static fields.
Note about the PIMPL idiom
Large class definitions inside a header file can multiply the project compilation time. To shorten it, you can put the class implementation in a separate compiled file. This means only the method declarations and a pointer to the class implementation will remain in the header file. This approach is called PIMPL. Here is an example of such a class:
#include <memory>
// header
class MyClass
{
class impl;
std::unique_ptr<impl> pimpl;
public:
void DoSomething();
~MyClass();
};
// cpp-file
class MyClass::impl
{
public:
impl()
{
// does nothing
}
~impl()
{
// does nothing
}
void DoSomething()
{
// ....
}
};
void MyClass::DoSomething()
{
pimpl->DoSomething();
}
MyClass::~MyClass() {}
The destructor of the 'MyClass::impl' class is needed for 'std::unique_ptr', but is unknown at this stage. So if you add '= default' to the destructor in the class body, you will get compilation errors. With this approach, special functions will be implemented in a compiled file.
When you move the definition of special functions from the class body, their empty bodies can also be replaced with '= default'. This will not increase performance, but it will make the code cleaner and easier to understand:
MyClass::~MyClass() = default;