Table of Contents
Introduction to Dynamic Memory
In the most part of the programs that were written before we used only static memory allocation. This means that we had to determine the amount of memory needed for program before runtime. Static memory allocation consists in allocating memory in compile-time before program is executed.
All the variables, declared in functions (including main() ) will be placed in the stack. Stack is the special region of the computer’s memory, where temporary variables are stored. Stack is First In Last Out (FILO) data structure. When a function declares a variable, this variable is pushed into the stack. Once the function exits, variable is popped from stack.
The heap is a region of computer’s memory, used for dynamic memory allocation. When you use dynamic allocation, all the created variables are stored into heap, Heap memory is not managed automatically. When you use dynamic memory allocation, a pointer that is located in stack points to the region of the allocated memory in heap:
To allocate and de-allocate memory in the heap you have to use special operators.
Why do we need to use dynamic memory?
Some of the tasks lead to the need to determine the amount of memory in runtime. For example, here is a simple task that leads to dynamic memory allocation:
Ask user to enter the number of elements.
Take input from user.
Display all the entered elements.
In this case, the program does not “know” how many elements will be entered by the user before execution. The program has to allocate memory for input during runtime after user inputs number of elements.
Operator new
For dynamic memory allocation, C++ offers operator new. Operator new returns the pointer to the newly allocated space. If you want to allocate memory for one single element of a specified data type (it can be a built in data type, structure or class), you will have to use operator new in the following form:
new data_type;
If you want to allocate memory for an array, you will have to use another form of operator new:
new data_type[size_of_array];
The common scheme for dynamic memory allocation consists of two parts:
- Declare a pointer.
- Allocate needed amount of memory.
Example
Here is the solution of the task described above:
int* arr;//pointer to int int n;//number of elements cout << "Please, enter the number of elements for input" << endl; cin >> n; // get n arr = new int[n];//allocate memory for array of int of size n //get user’s input cout << "Enter " << n << " elements" << endl; //get elements in loop for (int i = 0; i != n; ++i) cin >> arr[i]; cout << "You entered :" << endl; for (int i = 0; i != n; ++i) cout << "arr[" << i << "] = " << arr[i] << endl;
This code provides the following output:
Please, enter the number of elements for input
5
Enter five elements
1
2
3
4
0
You entered:
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 0
Safety
In the case when operator new fails to allocate memory, exception of type bad_alloc is thrown. There is a possibility to use “no throw” version of the operator new. In this case, you have to use the following syntax:
new (nothrow) data_type
Operator new will not throw exception even if it cannot allocate memory. It will simply return an empty pointer.
Dynamic memory allocation for one-dimensional arrays
When operator new is used to allocate memory for an array, memory is allocated consecutively. In the previous example:
arr = new int[n];//allocate memory for array of int of size n
n consecutive blocks of memory of size that is equal to size of int are allocated.
Try to modify the output of the array elements with adding information about the location of the array elements:
cout << "arr[" << i << "] = " << arr[i] << " location: " << &arr[i] << endl;
Also, get the information about size of int in your system:
cout << "Size of int in this system is " <<sizeof(int) << endl;
Try to run this modified version of the program:
Please, enter the number of elements for input
5
Enter 5 elements
1
2
3
4
5
Size of int in this system is 4
You entered:
arr[0] = 1 location: 00CA86D8
arr[1] = 2 location: 00CA86DC
arr[2] = 3 location: 00CA86E0
arr[3] = 4 location: 00CA86E4
arr[4] = 5 location: 00CA86E8
As you can see, next element has offset of size 4 bytes from the previous element (It can be different for different systems). The size of int is 4 bytes in my system.
Dynamic memory allocation for two-dimensional arrays
Often there is a need to allocate a memory for a two-dimensional array that is pointed up by a pointer to pointer. As you know from the “C++ Arrays”, two-dimensional array is an array of arrays. A dynamic 2D array is a pointer to an array of pointers to arrays.
If you want to allocate memory for a two-dimensional array dynamically, you have to create a pointer to pointer firstly:
int** arr2D;
After this, you have to allocate memory for the array of pointers that will store the pointers to arrays:
arr2D = new int*[5];
Now, use a loop to allocate memory for each row of two-dimensional array:
for (int i = 0; i != 5; ++i) arr2D[i] = new int[3];
The code above allocates memory for an array of size 5×3.
Operator delete
Once you do not need memory allocated by operator new, you have to release it. You can do it by using operator delete:
delete pointer; for single object and
delete[] pointer; for an array of objects
In this case, a pointer is passed to the array as a parameter
For example, we can free memory, allocated for array arr from the example above:
delete[] arr;
Operator delete for 2D arrays
If you want to free memory that was allocated for two-dimensional array dynamically, you have to free memory that was allocated for each row firstly. It can be done in a loop:
for (int i = 0; i != 3; ++i) delete[] arr2D[i];
After this, delete the pointer to the array of pointers:
delete[] arr2D;
When null pointer is passed to the operator delete, no effect will be produced.