xmllmx
xmllmx

Reputation: 42255

Should the user-defined empty destructor never be used?

struct A1
{
    ~A1() {} // A1 is not trivially destructible
};

struct A2
{
    ~A2() = default; // A2 is trivially destructible
};

A2 is better than A1, because A2 is trivially destructible while A1 isn't.

I think maybe we can safely say:

1. The user-defined empty destructor should never be used.

2. Any user-defined empty destructor should be replaced with the defaulted one.

Am I right?

Upvotes: 1

Views: 691

Answers (2)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275385

In the header file:

struct some_secret_type;
struct some_public_type {
  some_public_type();
  ~some_public_type();
private:
  std::unique_ptr<some_secret_type> pImpl;
};

Then, in the cpp file:

#include <some_secret_type.h>

some_public_type::~some_public_type() = default;
some_public_type::~some_public_type() {};

Here I have explicitly declared a destructor that ended up being either empty or defaulted.

The effects of =default; and {} here are identical in the cpp file.

In the header file, having either a {} or =default would require everyone including it know what some_secret_type looks like.

In a more general case, {} and =default in the header can change if a type is trivially destroyed. In the cpp/header split, they do not.

The advantage of {} in the header is that you prevent a type from being trivial (suppose later you know you are going to make it non-trivial, and you don't want other behavior changes to happen when you do it).

In the cpp file case, {} saves a few characters.

Upvotes: 2

besc
besc

Reputation: 2647

You can see a use case for such an empty destructor right there in your example. You can use it to force a trivial type to become non-trivial. That’s an outstandingly unlikely use case. But I wouldn’t be confident at all to call it never useful.

You’re not far off the mark, though. In a decade of programming C++ every day I’ve seen a lot of empty destructors, but not a single one that couldn’t be replaced with =default or omitted entirely.

Still, I’d be wary of a mechanical replacement. So:

  1. The user-defined empty destructor should almost never be used.

  2. Almost every user-defined empty destructor should either be omitted entirely (preferred option) or replaced with the defaulted one.

Upvotes: 2

Related Questions