8

If I do not provide an explicit destructor for a C++ class because I'm confident that the default destructor provided by the compiler is all my class needs, is that fine? Or is this considered bad practice?

justin
  • 104,054
  • 14
  • 179
  • 226
Cricketer
  • 2,391
  • 4
  • 24
  • 29
  • 2
    Good practice, more like. The need to provide your own doesn't come all that often. – chris Jul 09 '13 at 06:43
  • If you don't need one, why would you define it? – perreal Jul 09 '13 at 06:45
  • An explicit destructor definition is only necessary in class hierarchies that use virtual methods. – πάντα ῥεῖ Jul 09 '13 at 06:46
  • @g-makulik, Or in classes like `std::string`, though that situation arises for us about once every never. – chris Jul 09 '13 at 06:48
  • 1
    I think you should *know* when you need a user-defined dtor, not just *be confident that the default one will be fine*. – dyp Jul 09 '13 at 06:50
  • 1
    There is the fact that needlessly defining your own can change the classification of your class as well, when it depends on having no user-defined destructors. – chris Jul 09 '13 at 06:51
  • 4
    You could always explicitly declare it `~MyClass() = default;`. I do that when a class has some less trivial resources but still no need for a specialized destructor. It reminds me I didn't forget the destructor and should take another look if I change the class. Same goes for copy/move/assignment. – KillianDS Jul 09 '13 at 06:53
  • It gives me a syntax error if I use "= deafult" – Cricketer Jul 09 '13 at 07:03
  • Just found out that default is a C++11 feature. Thanks :) – Cricketer Jul 09 '13 at 07:05

5 Answers5

7

Explicit destructors are needed only in two cases:

  • When you need runtime polymorphism. In this case, the base class destructor needs to be virtual — this requirement forces you to explicitly define the destructor (even if it is empty!). The derived classes, however, may or may not have explicit destructor depending on whether they manage resources or not (which is the second bullet point).

  • When your class is a resource managing class — that is, it implements RAII idiom. In this case, you may also need to implement copy-semantics and move-semantics.

In all other cases, explicitly defined destructor is not needed. :-)

Nawaz
  • 353,942
  • 115
  • 666
  • 851
7

The main advantage of providing the explicit destructor is that you can easily put a breakpoint into it for debugging. Some people like that and prefer to give every class an explicit destructor because of that.

However, if the class is trivial enough that it is obvious that the default constructor suffices, it is perfectly fine to omit it. Also note that adding a destructor does have its disadvantages: Apart from the additional noise in the code, adding a destructor might prevent your class from being a POD. So you should still avoid mindlessly spreading trivial destructors throughout your code.

The only situation in which I would consider it harmful to omit an empty non-virtual destructor is when it is not obvious why destruction is trivial (e.g. if the rule-of-three/rule-of-five would suggest that you'd need one). In this case I would still provide an explicit empty destructor with a comment in the body why it is safe to not do anything. But that is more a personal preference than a fixed rule.

Community
  • 1
  • 1
ComicSansMS
  • 51,484
  • 14
  • 155
  • 166
  • 3
    Providing the destructor only for debugging reasons should be done only temporarily. You don't want to clutter your code with hundreds of destructors only because you might need one or two of them in desperate times. Good point on the explicitly defaulted destructor for the Ro3 (Ro5 since C++11) though. – Arne Mertz Jul 09 '13 at 07:05
  • Talking about good/bad practice, I believe that ALWAYS putting an explicit destructor is a better idea. You end up with more consistency and people can directly see that you did not "forget" the destructor. – Korchkidu Jul 09 '13 at 07:08
  • 4
    @Korchkidu I would see an unnecessary destructor as a sign that the author of the code didn't know what they were doing. To me it is distracting noise. – juanchopanza Jul 09 '13 at 07:20
  • 1
    @Korchkidu I disagree. Not needing and thus not writing the destructor should be the norm. If there's no need to write one, there is nothing to forget. – Arne Mertz Jul 09 '13 at 07:20
  • 2
    @Korchkidu Beware that indiscriminately providing an explicit destructor might be the only thing preventing your class to be a POD in C++03. – KillianDS Jul 09 '13 at 07:21
  • 1
    @Korchkidu and autimatically providing an empty destructor will make it hard to spot the cases where the dtor should have an actual implementation. Don't clutter your code with meningless noise. – Arne Mertz Jul 09 '13 at 07:24
  • Thanks for the excellent input everyone. Adjusted the answer to point out the dangers mentioned here. – ComicSansMS Jul 09 '13 at 07:35
  • @juanchopanza: " I would see an unnecessary destructor as a sign that the author of the code didn't know what they were doing". Why that? He is clearly stating his mind. While ignoring it could be the resul of a "let's see what happens. YES, it works!" syndrom. How could you be sure? – Korchkidu Jul 09 '13 at 09:29
  • @KillianDS: indeed. This is indeed a good reason not to systematically provide an empty destructor. – Korchkidu Jul 09 '13 at 09:30
  • @Korchkidu Why that? I have observed a strong correlation after many years working with large groups of developers. – juanchopanza Jul 09 '13 at 09:43
  • @juanchopanza: my point is just that it is hard to tell the "awareness" difference between some dev who ALWAYS add a default destructor, and some dev who NEVER does... – Korchkidu Jul 09 '13 at 10:25
1

Yes, that's perfectly fine. You have mainly three reasons to provide a destructor yourself:

  1. You are defining a base class of a class hierarchy, whose objects will be destroyed polymorphically. You then need to define the destructor public and virtual (and defaulted, see later).
  2. You are defininig a base class in a hierarchy that will not have its objects destroyed polymorphically. Since in good OO-practice you won't instanciate objects of that base class, you make the destructor nonvirtual, protected (and defaulted).
  3. You are defining a class that owns a resource. You'll have to obey The Rule of Five and define the destructor to release the resource.

Case 1 and 2 are mutually exclusive, and in case 3 the SRP demands that the class' purpose is solely management of the owned resource, so it should not be a base class, making all three cases mutually exclusive. That's the reason why the base class destructors and almost any "normal class" destructor should be defaulted (see this article about The Rule of Zero).

Of course there are many corner cases that don't exactly fit into that scheme and where destructors are needed in some cases. But generally, if you are sure the defaulted destructor does what is needed, you don't need to define it yourself.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Arne Mertz
  • 24,171
  • 3
  • 51
  • 90
0

It depends on what your constructor is doing. C++ does not provide garbage collection so if your constructor is creating new objects it would be good to delete them in destructor. Memory used for class members is freed anyway so if you are not using "new" in constructor and not allocating memory in any other way, destructor is not mandatory.

fsw
  • 3,595
  • 3
  • 20
  • 34
0

Where applicable, you should generally provide an out of line definition if:

  • The destructor is virtual and your class provides no out of line virtual definitions (remember that bases with virtual destructors make your destructor virtual). Many implementations emit vtables and RTTI info in the translation which contains the definition of the first out of line virtual member function. This can result in a lot of cloned information, if the type is visible to many translations.

  • or if the destruction of the members is 'heavyweight'

These two can shave a big chunk off your binary size and build times.

You may also define it out of line in order to correctly delete a PIMPL member (based on which headers are visible where and the mechanics of your smart pointers).

justin
  • 104,054
  • 14
  • 179
  • 226