Skip to content

ILXL-guides/dynamic_memory_allocation

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dynamic memory allocation

Dynamic memory allocation allows C++ programs to create data structures in the heap so that it is not limited by the stack's size.

Dynamically allocating an array of dynamically allocated objects

Dynamically allocating an array is useful because it allows us to create a container of dynamic size in the heap. We have already seen how to dynamically create an array of primitive data types and objects as shown below.

int* values = new int[10];
student* cpsc121 = new student[60];

However, it is also possible to dynamically create an array of pointers. This is especially useful when dealing with object pointers to allow polymorphism. The syntax might be confusing at first, but it just builds on what we already know.

First thing to consider is that we use the * during variable declartion to indicate the creation of a pointer to the specified data type. int* values, for example indicates that we create a pointer to an int.

When arrays are dynamically allocated, the compiler reserves space that can contain a consecutive list of data with a certain data type. When we allocate memory using new int[10], for example, the compiler looks for an available block of space to hold 10 integers that is around 40 bytes of memory (4 bytes x 10).

The new keyword returns the address of the first element of the array. Essentially, this means the address returned is the address of the first element of the array with the specified data type. In our example, it will return the address of the first int in the array. This is the reason why we can assign this to an int*.

The dynamic_arrays.cpp file provides sample code that you can run and compile.

Now consider creating an array of int pointers (or int*). Every element of the array would hold the address of an int and can be written as new int*[10]. We can use the same pattern to create an array of object pointers. For example, new student*[10].

What data type should we use to declare a variable to hold the dynamically created array of pointers? Going back to our prior discussion, we established that int* values can be used to store the address of the first int of a dynamically created int array. The difference now is that instead of storing the address of the first element that is a primitive data type or object, we are talking about an address.

If int* is a pointer to an int, then int** would be a pointer to an int* (the address of an integer). Similarly, we can use this notation to create a pointer to any object address. For example, student**. Putting these concepts together we can now create a dynamically allocated array of addresses and store the address of the first element of that array into a variable.

int** value_locations = new int*[10];
student** cpsc121_locations = new student*[10];

The first statement creates an array of 10 int* (int pointers). The first element of that array is an int* therefore the data type of the variable value_locations should be a pointer to an int* (int pointer), thus int**. Similarly, cpsc121 is a pointer that points to the first element of the array of student* (student pointers).

Accessing elements of a dynamically created array of pointers

Take note that the array we created contains addresses instead of the values. Therefore elements accessed using the bracket notation or pointer arithmetic are themselves addresses. To display an element of the dynamically allocated array of int pointers, we would now need to retrieve the address using the bracket notation or pointer arithmetic and then dereference it.

int i = 5;
int* values = new int[10]; // dynamic array of int
values[i] = 35; // assign value to element in index i
cout << values[i]; // bracket notation
cout << *(values+i); // pointer arithmetic

Although it looks more complex, we apply the same logic for a dynamically created array of object pointers

int i = 5;
student** cpsc121_locations = new student*[10]; // dynamic array of student pointers

cpsc121_locations[i] = new student; // create a student object and store its address in index 5 of the array

// Variations for accessing the student object's functions
(*cpsc121_locations[i]).set_name("Julian"); // bracket notation and dereferencing to call method
cpsc121_locations[i]->set_id(12345); // bracket notation and arrow notation to call method
(*(*(cpsc121_locations+i))).display(); // pointer arithmetic and dereferencing to call method
(*(cpsc121_locations+i))->display(); // pointer arithmetic and arrow notation to call method

Deallocating the dynamically created array of pointers

Each element of the dynamically created array is itself an address that needs to be deallocated. Therefore we should not only deallocate the space used by the array, but also each address contained by its elements. We can use a loop to traverse the array and deallocate each element then deallocate the array as shown below.

for (int i = 0; i < 10; i++) {
  delete cpsc121_locations[i];
}
delete[] cpsc121_locations;

We use delete for each element of the array if it is the address of a single object. We use delete[] for the array.

The dynamic_pointer_arrays.cpp file provides sample code that you can run and compile.

You can also see pens.cpp and pens.hpp for a full example that uses dynamically allocated pointer arrays with polymorphism.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages