Team 2550
Technical Documentation
|
|
At some point, arrays become too big to store on the stack. This is called stack overflow.
0 1 2 3 Segmentation fault (core dumped)
The sole purpose of the function above is to allocate a lot of memory. As programs get larger and more complex, it becomes increasingly difficult to stay within the bounds of the memory that the operating system gives your program when it is launched. In order to use more memory, you have to manually allocate it as needed at runtime. This is where dynamic memory comes in. C++ has some special built-in functions that request more memory from the operating system and return pointers to that extra space. The cost of dynamic memory is that it is much slower: by using it, you sacrifice speed for flexibility.
In order to dynamically allocate a value, you have to use the new
operator – it requests the operating system for a block of memory and then returns a pointer to that location.
0x7fff82376378 73
new
operation must have a corresponding delete
. Read about that in the next section.The delete
operator de-allocates memory so that the operating system can use it again.
38 0
There is one problem in the above code. Look at the output, the second value is 0. However, this could easily be something else. delete
de-allocates the memory so that it can be overwritten by the operating system. It is always best to assign the pointer to some other location of NULL
.
38 0 Segmentation fault (core dumped)
The use of the delete
operator is necessary when working with dynamic memory. Failure to do so will create a memory leak. A memory leak occurs when a pointer pointing to dynamic memory is changed or inaccessible. For instance, a function that does not use the delete operator on an internal pointer. You can no longer access that value, and the system cannot take it back. This can cause problems if your program uses a large amount of memory.
malloc()
and free()
functions in older code. These functions are the equivalent to new
and delete
in C. C++ still supports them for historical reasons. Do not use them in your code. They completely ignore constructors and destructors.Arrays can be allocated easily. Just use the new
and delete
operators.
You can access the elements of the array using the standard array subscript notation.
x[103] = 32;
Large arrays are not the only benefit of dynamic arrays. The size of a stack-allocated array is set at compile-time, however, the size of a dynamic array can be determined at runtime. The code below should result in a compiler error.
The following code shows one example where you would want to use a dynamic array. It prompts the user to put in an array size, requests a value for each element, and then prints the final array.
Enter the array size: 8 Input x[0]: 431 Input x[1]: 541 Input x[2]: 63 Input x[3]: 1 Input x[4]: 34 Input x[5]: 63524 Input x[6]: 1543155 Input x[7]: 6513 x[0] = 431 x[1] = 541 x[2] = 63 x[3] = 1 x[4] = 34 x[5] = 63524 x[6] = 1543155 x[7] = 6513
Allocating a multidimensional array is more complex. You have to loop through each additional level and use pointers to pointers.
It is important to realize that allocating a multi-dimensional array to the heap is significantly different from the stack. Instead of the allocation in the multidimensional arrays section, heap-allocated memory can be wherever the system finds free space. This results in a noticeable speed reduction.
Instead of a table like this...
x[3][2] in Memory | |
---|---|
Address | Name |
1000 | x[0][0] |
1001 | |
1002 | |
1003 | |
1004 | x[0][1] |
1005 | |
1006 | |
1007 | |
1008 | x[1][0] |
1009 | |
1010 | |
1011 | |
1012 | x[1][1] |
1013 | |
1014 | |
1015 | |
1016 | x[2][0] |
1017 | |
1018 | |
1019 | |
1020 | x[2][1] |
1021 | |
1022 | |
1023 |
A dynamically allocated array with the same dimensions would look more like this...
Objects can be dynamically allocated as well. Here, we will cover two situations: classes containing pointers and dynamically-allocated classes.
Classes containing pointers typically allocate memory in the constructor and de-allocate using the destructor. Let's create a dummy class to demonstrate this.
Dummy constructor run. Dummy destructor run.
Every time you create a class, you actually create two data types: the class datatype and the class pointer datatype. In other words, you create DummyClass
and DummyClass*
. When using a pointer to a class, new
calls the constructor and delete
calls the destructor. The files below demonstrate how class pointers work.
Dummy constructor run. 43125 15 Dummy destructor run.
Although the above class is basically useless, it does demonstrate how class pointers work. There are certain situations where a particular class stores a lot of information but you need a very large number of them. This is the kind of situation where it could be useful to store an array of class pointers or a dynamically allocated array of class pointers.
->
operator as opposed to the dot operator.Dynamic memory has many practical uses. I would encourage you to research data structures, as they use dynamic memory to organize large amounts of data efficiently.