Dynamic Memory Allocation and Operators new and delete

In this tutorial, we will learn a new way to declare variables, using the new operator and pointers, in C++.

Dynamic Memory Allocation in C++

Let's assume that you are going to make software for the multinational you work for.
It has 1000 employees.

Then, you will declare, among several things, a thousand variables of type int to store the age of each person, a thousand variables of type double to store the salary of each person, a thousand strings to store the name of each person, etc., etc.

However, his company has grown, and now has 2,000 employees.
And now, go back to the code and change everything?

So far, in our C++ course, we have declared fixed values, exact values ​​of memory blocks, but this is not always interesting in the world of computing. Often you don't know how many variables you will need to use, so you don't know how many variables you will need to declare.

For example, if you are going to create a new social network, how much memory space will you need to store user data? Hey, you don't know ... after all, it may have a thousand or a million users, who knows.

What you have to do is then allocate memory dynamically. That is, it will allocate as needed.

Pointers and the Operator new

Let's say you want to allocate space for a variable of type double.
You will ask, via C++ code, for the computer to find a free memory block on the machine that you can allocate for yourself.

It then goes there to search your system, finds a block and returns the starting address of that block, the address of the first byte. Now, if it returns you an address, what do you need to keep that kind of information?

Yes, our beloved type, the pointer.
This allocation request is made with the new operator.

Here is a code example that we allocate a block of memory for a variable of type double:
#include <iostream>
using namespace std;

int main()
{
    double *ptr;
    ptr = new double;
    *ptr = 3.14;

    cout << *ptr << endl;

    return 0;
}
When we type 'new double', the machine returns a memory address, the first of the block reserved for the double, and stores that address in the 'ptr' pointer, which obviously must be of the double type as well (that is, it points to the address of an 8-byte block, space required for a double).

See, we haven't defined any variables purely of type double. We only have a pointer that points to a block that has a value of type double.

We can even change this stored value using *ptr:
#include <iostream>
using namespace std;

int main()
{
    double *ptr;
    ptr = new double;
    cin >> *ptr;

    cout << *ptr << endl;

    return 0;
}
Everything we could do with a variable of type double, we can do with this pointer.

We can also allocate entire arrays, with the new operator, see:
#include <iostream>
using namespace std;

int main()
{
    int *ptr;
    ptr = new int[10];

    for(int aux=0 ; aux<10 ; aux++){
        ptr[aux] = aux+1;
    }

    for(int aux=0 ; aux<10 ; aux++){
        cout << ptr[aux] << endl;
    }

    return 0;
}
In the code above, we allocate an array of 10 integers, and fill in the numbers from 1 to 10.
That is, in the first example, ptr 'became' a double. In this example above, ptr 'became' an array of integers.

These pointers are flexible, aren't they?

Free memory spaces - Operator delete

Another advantage of using memory allocation dynamically, is the possibility of also freeing that memory that has been allocated, just by using the delete operator.

In the first example, we deallocate the memory block like this:
#include <iostream>
using namespace std;

int main()
{
    double *ptr;
    ptr = new double;
    cin >> *ptr;

    cout << *ptr << endl;

    delete ptr;

    return 0;
}
In case it is an array, we place the pair of square brackets [] before the pointer name:
#include <iostream>
using namespace std;

int main()
{
    int *ptr;
    ptr = new int[10];

    for(int aux=0 ; aux<10 ; aux++){
        ptr[aux] = aux+1;
    }

    for(int aux=0 ; aux<10 ; aux++){
        cout << ptr[aux] << endl;
    }

    delete [] ptr;

    return 0;
}
This may seem strange nowadays, if you imagine your PC with several and several Terabytes, there is no need to free up allocated memory during the execution of a program.

However, this knowledge and practice is essential in critical systems that consume a lot of memory, such as in a very high level game or in a super efficient operating system, you cannot leave everything allocated forever, you have to release it gradually.

In systems with little memory space (like your digital clock, the panel of a refrigerator or the timer of your microwave), it is vital to deallocate and free up memory, as this resource is very scarce.

We will study the new operator in more detail when we study Classes and Objects, in Object Oriented Programming.

No comments:

Post a Comment