Reputation: 233
For what situations we need to have a default generated destructor? It's pretty clear why we would need default generated constructors and operator=, but can't think of situation when default generated destructor should be used.
class A
{
...
~A() = default;
...
};
Upvotes: 0
Views: 689
Reputation: 5232
Reason
The semantics of copy, move, and destruction are closely related, so if one needs to be declared, the odds are that others need consideration too.
Declaring any copy/move/destructor function, even as =default or =delete, will suppress the implicit declaration of a move constructor and move assignment operator. Declaring a move constructor or move assignment operator, even as =default or =delete, will cause an implicitly generated copy constructor or implicitly generated copy assignment operator to be defined as deleted. So as soon as any of these are declared, the others should all be declared to avoid unwanted effects like turning all potential moves into more expensive copies, or making a class move-only.
Note If you want a default implementation (while defining another), write =default to show you're doing so intentionally for that function. If you don't want a generated default function, suppress it with =delete.
So this mainly depends on what is declared in the class.
Generally it is about The rule of three/five/zero
If the class needs a custom copy/move function, but nothing special for a destructor, then =default
should be used on the destructor.
Upvotes: 0
Reputation: 118097
In cases where you'd like to hide the implementation of a class inside an inner class and keep a unique_ptr
to an instance of that inner class (the pimpl idiom) you need to move the default
destructor definition out of the class definition since unique_ptr
can't work with incomplete types.
Example:
A.hpp (the header a user of the class will include)
#pragma once
#include <memory>
class A {
public:
A();
~A();
void foo() const;
private:
struct A_impl; // just forward declared
std::unique_ptr<A_impl> pimpl;
};
A_impl.hpp ("hidden" - not to be included in normal usage of A
)
#pragma once
#include "A.hpp"
struct A::A_impl {
void foo() const;
};
A.cpp
#include "A_impl.hpp"
A::A() : pimpl(std::make_unique<A_impl>()) {}
A::~A() = default; // <- moved to after A_impl is fully defined
void A::foo() const { pimpl->foo(); }
A_impl.cpp
#include "A_impl.hpp"
#include <iostream>
void A::A_impl::foo() const { std::cout << "foo\n"; }
If you let the compiler generate A::~A()
it will not compile. My compiler says:
unique_ptr.h:79:16: error: invalid application of ‘sizeof’ to incomplete type ‘A::A_impl’
static_assert(sizeof(_Tp)>0,
^~~~~~~~~~~
Upvotes: 2
Reputation: 7528
This seems to be asking when you would define the destructor for a class if the body of that destructor would be the same as the one the compiler generates.
Reasons include:
In all these cases, you must or want to define the destructor, even though the body is nothing special. Why would you use = default
versus an empty body? Because the compiler-generated destructor is equivalent to the one you get with = default
, and you only want to change the aspects of the destructor you are trying to change. An empty body is not the same as = default
in C++, because a defaulted function can be defined as deleted. An empty body also rules out trivial destructibility, even if that was otherwise an option.
Upvotes: 0