When should I provide a destructor for my class?

This seems like a pretty trivial, or at least a general question, but I could not find a satisfactory answer on google or on SO.

I am not sure when I should implement a destructor for my class.

The obvious case is that the class wraps the connection to the file, and I want to make sure that the connection is closed, so I will close it in the destructor.

But I want to know in general how I can find out if I should define a destructor. What recommendations exist to check if I should have a destructor in this class?

One such recommendation that I can think of is that the class contains any pointers to elements. The default destructor will destroy pointers when deleted, but not the objects they point to. Thus, this should be the work of a user-defined destructor. For example: (I am new to C ++, so this code does not compile).

class MyContainer { public: MyContainer(int size) : data(new int[size]) { } ~MyContainer(){ delete [] data; } // .. stuff omitted private: int* data; } 

If I did not provide this destructor, then destroying the MyContainer would mean creating a leak, since all the data previously mentioned by data would not be deleted.

But I have two questions:

1- Is this the only "benchmark"? That is, to determine the destructor if the class has pointers to an element or if it controls the resource? Or is there anything else?

2- Are there any cases where I should not indicate pointers to delete elements? What about links?

+7
c ++ memory-management pointers destructor
source share
3 answers

You need to define a destructor if default destruction is not enough. Of course, this just asks the question: what does the default destructor do? Well, he calls the destructors of each of the member variables and what he is. If this is enough for you, you are well off. If this is not the case, you need to write a destructor.

The most common example is when a pointer is placed with a new one. A pointer (for any type) is primitive, and the destructor simply forces the pointer to leave without touching the pointer to memory. Thus, the default pointer destructor does not have the correct behavior for us (this will lead to a memory leak), so we need a delete call in the destructor. Imagine now that we change the pointer to a smart pointer. When a smart pointer is destroyed, it also calls the destructor of what it points to, and then frees memory. Thus, a smart pointer destructor is sufficient.

Understanding the root cause of the most common case, you can talk about less common cases. It is true that very often, if you use smart pointers and std library containers, their destructors do the right thing, and you don’t need to write a destructor at all. But there are still exceptions.

Suppose you have a Logger class. This logger class is intelligent, but it buffers a bunch of messages in the log, and then writes them to a file only when the buffer reaches a certain size (it "flushes" the buffer). This may be more effective than immediately dumping everything into a file. When the Logger is destroyed, you need to flush everything from the buffer, regardless of whether it is full, so you probably want to write a destructor for it, although it is quite easy to implement Logger in terms of std :: vector and std :: string, so nothing flows when it is destroyed.

Edit: I have not seen question 2. The answer to question 2 is that you should not call delete if it is a non-owner pointer. In other words, if any other class or area of ​​responsibility is solely responsible for cleaning up after this object, and you have a pointer to “just look,” then do not call delete. The reason is that if you call delete and someone else owns it, the pointer deletes it twice:

 struct A { A(SomeObj * obj) : m_obj(obj){}; SomeObj * m_obj; ~A(){delete m_obj;}; } SomeObj * obj = new SomeObj(); A a(obj); delete obj; // bad! 

In fact, perhaps the manual in C ++ 11 should NEVER call delete on a pointer. What for? Well, if you call delete on a pointer, that means you own it. And if you own it, there is no reason not to use a smart pointer, in particular unique_ptr - almost the same speed and does it automatically, and is much more likely to be thread safe.

Also, besides (excuse me that I'm really getting into it now), it's usually a bad idea to make unexplored representations of objects (source pointers or links) members of other objects. What for? Since an object with a raw pointer may not have to worry about destroying another object, since it does not own it, but it does not know when it will be destroyed. The specified object can be destroyed while the object with the pointer is still alive:

 struct A { SomeObj * m_obj; void func(){m_obj->doStuff();}; } A a; if(blah) { SomeObj b; a.m_obj = &b; } a.func() // bad! 

Please note that this applies only to the fields of object objects. Passing the representation of an object into a function (member or not) is safe because the function is called in the scope of the object itself, so this is not a problem.

The harsh conclusion to all of this is that if you don’t know what you are doing, you simply should not have the original pointers or references as fields of object objects.

Edit 2: I think the general conclusion (which is really good!) Is that in general your classes should be written in such a way that they do not need destructors unless the destructors do something semantically meaningful. In my example, Logger Logger must be reset, something important must happen before it is destroyed. You should not write (usually) classes that must perform a trivial cleanup after their members, member variables must clean up after themselves.

+9
source share

A destructor is useful when your classes contain dynamically allocated memory. If your classes are simple and do not have a "DAM", then it is safe not to use a destructor. Also, read about Rule Three . You should also add a copy constructor and an overloaded = operator if your class has "DAM".

2) Do not worry about links. They work differently, for example, "Refers" to another variable (which means that they do not indicate memory).

+1
source share

A class needs a destructor when it "owns" the resource and is responsible for clearing it. The purpose of the destructor is not just to make the class itself work correctly, but to make the program as a whole work correctly: if the resource needs to be cleared, something needs to be done, and therefore some object should take responsibility for cleaning .

For example, you may need to free memory. You may need to close the file descriptor. You may need to disconnect the network socket. You may need to remove the graphics device. These things will remain if they are not clearly destroyed, and therefore something must destroy them.

The purpose of the destructor is to associate the resource of the resource with the object, so that the resource leaves when the object leaves.

+1
source share

All Articles