Allocate Memory in Constructors and Destructors

Summary

In this post, I will introduce the way to define a class which contains memory allocation. I will focus on constructors and destructors in this post.

Conclusion

I present the conclusion first as usual: whenever the implementation of a class involves dynamically allocated memory, the class should explicitly define:

  1. a destructor which frees the allocated memory;
  2. a copy constructor;
  3. an assignment operator;

Constructors and Destructors

  1. A class has at least one constructor, and has exactly one destructor;
  2. Constructors and destructors are not inherited;
  3. Unless Derived’s constructor explicitly calls one of Base’s constructor, the default constructor from Base will be called automatically before Derived’s constructor body (the idea being that Base needs to be initialized before Derived gets created);
  4. After Derived’s destructors exits (or the default destructor exits), B’s destructor will automatically call A’s destructor.

Assignment Operator and Copy Constructor

It relates to shallow copy and deep copy and the default copy constructor performs shallow copy which may cause problems. I will discuss it in another post.

Details

I come across this problem when designing the data structures in Project Knerex. After some research, I figure out the solution. For better understanding, I provide the following snippets for your reference.

Construtors and Destructors

In the destructors, we should free all the allocated memory.

class Base {
private:
    int *base_array;
public:
    Base() {
        cout << "base_array has been allocated!" << endl;
        base_array = new int[10];
    }
    ~Base() {
        delete base_array;
        cout << "base_array has been deleted!" << endl;
    }
};

class Derived : public Base {
private:
    int *derived_array;
public:
    Derived() {
        cout << "derived_array has been allocated!" << endl;
        derived_array = new int[10];
    }
    ~Derived() {
        delete derived_array;
        cout << "derived_array has been deleted!" << endl;
    }
};

int main() {
    {
        Base base;
    }
        /*
        base_array has been allocated!
        base_array has been deleted!
        */
    {
        Derived derived;
    }
        /*
        base_array has been allocated!
        derived_array has been allocated!
        derived_array has been deleted!
        base_array has been deleted!
        */
}

Reference

  1. wisc.edu
  2. stackoverflow
  3. stackoverflow

Leave a Reply

Your email address will not be published. Required fields are marked *