Home CPSC 340

Dynamic Memory Allocation

Allocating Memory

All of the memory for variables and objects we have used so far has been managed automatically for us. This means that the compiler sets up the space to store our variables for us.

However, many times we don't know when we're writing a program how much space we will need. Using dynamic allocation allows us to request memory while the program is actually running. In C++, this is done using the "new" keyword which returns a pointer to a fresh memory location.


int* ptr = new int;

Now the pointer ptr has the address of an integer that was allocated dynamically. Notice that the only way to access this value is through the pointer. The integer itself does not have a name.

We can initialize the newly created value by passing the initial value in parenthesis. This works for basic types as well as objects - in which case the initial values are passed to a constructor:


int* ptr = new int(42);
Circle* f = new Circle(2.0);

Deleting Memory

After requesting memory, we must always release it back. If memory is allocated, but not deleted, it results in a memory leak. We deallocate memory in C++ using "delete":


delete ptr;
delete f;

This program shows the basic usage of new and delete to allocate memory. When deleting a pointer to an object, the objects destructor is also called, if it has one.


Allocating Arrays

We can also use new to allocate an entire array of values at once. This is very useful because, with automatically allocated arrays, we can only have a fixed number of items. When we use new to allocate an array, it can be a number that is decided upon at runtime. When allocating an array, the size goes in brackets after new:


int* dynamic_array = new int[1000];

This allocates an array of 1000 integers and returns a pointer to the first one. Since pointers can be used as arrays, we can use dynamic_array exactly as any other array. When we de-allocate a dynamically created array, we must use a slightly different syntax:


delete [] dynamic_array;

The brackets are necessary when deleting an array. Without them, we would likely only delete the first element of the array, leaving the rest as a memory leak.


Dynamic Memory and Classes

When we declare dynamic memory inside of a class, we must be sure that we use it correctly and do not leak any memory. Typically, a class that needs dynamic memory will allocate it in the constructor, and de-allocate it in the destructor.

Destructors are special functions that classes in C++ can have which are automatically called when the object is no longer used (such as when it goes out of scope). A destructor is normally used to remove any resources that the object was holding. A destructor is named the same as the class, but preceded with the ~ symbol. Destructors take no arguments, and each class can contain only one.

This example shows how destructors are used:

The following class contains a constructor and also a destructor:


class Thing {
    public:
        Thing(int number) {
            n = number;
            cout << "Thing " << n << " created!" << endl;
        }

        ~Thing( ) {
            cout << "Thing " << n << " dead :(" << endl;
        }

    private:
        int n;
};

Destructors are automatically called when the object is no longer useable. Where will the destructors be called in the following program:


Thing t1(1);

int main() {
    Thing t2(2);

    {
        Thing t3(3);
    }

    Thing t4(4);

    return 0;
}

Copyright © 2018 Ian Finlayson | Licensed under a Creative Commons Attribution 4.0 International License.