0

Recently I am studying OOP using C++, and I am quite confused when I should use destruction function of my own in the following case:

class T1{
private:
    int data;

public:
    T1(){...};
    ~T1(){}; // should I write my own function here?
};

class T2{
private:
    T1* pointer_to_T1;

public:
    T2(){...};
    ~T2(){}; // should I write my own function here?
};

class Node{
public:
    int data;
    Node* next;
};

class T3{
private:
    int size;
    Node* head;
public:
    T3(size){
        head = new Node[size];
    }
    ~T3(){}; // should I write my own function here?
};

There are three comments in my program above to clarify my question. I hope you could explain them and I would appreciate it if you could give me a general rule.

7 Answers7

1

In case of class T3 you are allocating new memory, so you will have to delete the allocated memory segment in destructure.

class T3{
private:
    int size;
    Node* head;
public:
    T3(size){
        head = new Node[size];
    }
    ~T3(){
         delete[] head;
      }; 
};
rajenpandit
  • 1,265
  • 1
  • 15
  • 21
  • Now you have invalid copy semantics. You should also implement or delete the copy constructor and copy-assignment operator, per the [Rule of Three](http://stackoverflow.com/questions/4172722) or, better, use `std::vector` to manage the array automatically. – Mike Seymour Feb 20 '14 at 14:14
0

The destructor of a class should perform all actions needed when the object is deleted.

For example it need to free all the memory that was dynamically allocated by the class.

OlivierLi
  • 2,798
  • 1
  • 23
  • 30
0

You should write a destructor when your class is a base class, and you expect polymorphic destruction, and when you want some logic to be ran when the object is destroyed.

If the object owns and manages resources, you probably need a constructor. Don't forget about the copy and assignment operators.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
0

The object should cleanup after itself.

IE, if you ever allocate memory in your object, possibly being done in the constructor, then you should deallocate that memory in the destructor.

The destructor is meant to cleanup after your object. So it is also possible that you can do anything to help you do that.

Justin Wood
  • 9,941
  • 2
  • 33
  • 46
0

Class T1 does not require to define explicitly the destructor. It will be enough to have the destructor implicitly defined by the compiler.

Class T2 needs to define the destructor explicitly that to deallocate its data member having type pointer. Otherwise there will be a memory leak.

Class Node does not need to define the destructor explicitly. It is class T3 that has to delete all pointers of class Node because it is it that controls the allocation and deallocation of nodes.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • How do you know T2 owns the memory its member pointer addresses? – Luchian Grigore Feb 20 '14 at 14:08
  • @Luchian Grigore It is simply a bad design to use a raw pointer that is not owned by the class. – Vlad from Moscow Feb 20 '14 at 14:09
  • Well, it's bad design to use raw pointers anywhere... The point is this - it's about resource ownership, not whether the class has a pointer in it or not. It could be a file handle, not necessarily a pointer. – Luchian Grigore Feb 20 '14 at 14:15
  • @ Luchian Grigore If you mean my post then I supposed that it vis T2 that allocates the pointer. I am sure the same was supposed by the author of the tread. – Vlad from Moscow Feb 20 '14 at 14:21
0

You need to declare a destructor:

  • if the class manages resources that need to be manually released when it's destroyed;
  • if it's intended to be a polymorphic base class, in which case it needs a virtual destructor to allow polymorphic deletion.

In the first case, you'll also need to provide, or delete, a copy constructor and copy-assignment operator; otherwise you could end up with two or more objects trying to manage the same resource. This is known as the "Rule of Three". Usually, you can use ready-made classes like containers and smart pointers to manage memory for you; so there's usually no need to muck around with destructors yourself. Some people refer to this as the "Rule of Zero".

In the second case, the destructor doesn't have to do anything (assuming the class isn't trying to manage any resources), it just needs to be virtual.

For your specific examples:

  • T1 doesn't need a destructor
  • T2 might, depending on whether it's supposed to manage whatever the pointer points to. If it does, then consider replacing the pointer with a smart pointer like std::unique_ptr<T1>.
  • T3 probably does, since it appears to be managing the dynamic array. You'll also need to consider the Rule of Three; or consider using std::vector<Node> to manage the array automatically.
Community
  • 1
  • 1
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
0

I'll attempt to answer in a general way not specific to your code snippets.

Two general scenarios commonly present themselves in which you'll need a non-trivial destructor. This is not a complete list; just the most common scenarios.

1) In a (polymorphic) hierarchy. If your class is a base class, intended to be derived from, there is a very good chance that your base class should have a non-trivial destructor. Moreover, that destructor should probably be virtual. This makes it possible to delete derived-class objects through the base-class pointer, like this:

class Foo
{
public:
  virtual ~Foo(){}
};

class Bar : public Foo
{
};

int main()
{
  Foo* obj = new Bar;
  delete obj;
}

Without the virtual destructor, this program would exhibit Undefined Behavior.

2) When your class has members need more than trivial destruction. A simple example is if your class has a member that is a raw pointer (as in not a smart pointer) that was created using new. That pointer will need to be deleted, and the destructor is probably the right place to do it. A good indication that your class manages non-trivially-destructible members is if your class has either a copy constructor or a copy assignment operator (operator=). If your class has either then it probably needs both of them plus a destructor to handle whatever was assigned. (See Rule of Three) This isn't the only indication however -- you could have only a default constructor and still need a destructor. It depends on what your class does.

John Dibling
  • 99,718
  • 31
  • 186
  • 324