C++ Tour Part II

Pointers and Dynamic Memory

Dynamic memory is useful when you don't know the memory requirements at compile time.

Stack and the Heap

Memory is divided into the stack and the heap or free store. Stack memory is automatically managed, whereas heap memory is not. Activation Records are blocks of memory on the stack that are used to implement functions. For example, when main calls foofoo's activation record is at the top of the stack. Once foo returns, the activation record for foo is marked as deallocated, and another function call can make use of that space. Any parameters passed from main to foo are copied into foo's activation record. Below is an illustration for the activation record from Wikipedia:


Memory allocated on the heap lives indepedently of the function calls. Once has to make sure to deallocate memory allocated on the heap. Some languages such as C# and Python have garbage collection (GC) for this purpose but C++ does not. However, "smart pointers" help with automatic deallocation of memory. To explicitly allocate memory on the heap:
int* pointerToInt;
pointerToInt is currently an uninitialized pointer. Working with unitialized pointers will likely crash the program. One should always initialize pointers. They can be set to null (using nullptr), and checked against null. nullptr converts to false when used in a Boolean expression. Example:
if(!pointerToInt)
{
    //execute code that handles null pointer case
}
The new operator is used to allocate memory.
pointerToInt = new int;
To access the newly allocated value, one has to dereference the pointer, or follow the pointer's address to memory. For example, setting the value of the pointer above can be done as follows:
*pointerToInt = 42;
To deallocate memory, one has to use the delete operator and it is best practice to then set the pointer to nullptr:
delete pointerToInt;
pointerToInt = nullptr;
One can also declare and initialize pointers that point to variables on the stack. To obtain a pointer to a variable, use the & or address-of operator:
double k = 42.0
double* kPtr = &k;
Typically to get at the fields of a structure via a pointer one has to do the following:
Person * person = getPerson();
double address = (*person).address;
There is a shorthand for the (*ptr). notation and it is the arrow notation. The same code can be written as follows:
Person *person = getPerson();
double address = person->address;
To avoid using an invalid pointer, one can take advantage of short circuiting logic:
bool hasValidAddress = (person && person->address != "")

Dynamically Allocated Arrays

To allocate arrays on the heap use the new[] operator as follows:
int arySize = 10;
int* ptrToDynamicAry = new int[arySize]; 
The next figure shows the programmer's mental memory model after the previous code is executed:




When finished with the array, one has to deallocate the array from the heap. The "array" version of the delete operator should be used for this:
delete[] ptrToDynamicAry
ptrToDynamicAry = nullptr;

Smart Pointers

To avoid memory leaks one can use smart pointers. The following two pointers std::unique_ptr and std::shared_ptr are the most commonly used and defined in the <memory> header file. unique_ptr is similar to a raw pointer but automatically frees the memory after it goes out of scope or is deleted. unique_ptr is the sole owner of the object it points to. Even when an exception is thrown, the memory pointed to by the unique pointer is deallocated. The syntax for a unique_ptr is as follows:
auto person = std::make_unique<Person>(); 
Prior to C++14, one had to do the following:
std::unique_ptr<Person> person(new Person);
unique_ptr can be used similar to a normal pointer as it overloads the arrow operator (->) and the indexing operator ([]).
The previous example of a dynamic array translates to the following when using unique_ptr:
auto myAry = std::make_unique<int>(10);
cout << "Integer at position 5 is " << myAry[4] << endl;

References:

Gregoire, M. (2018). Professional C++. Indiana, IN: John Wiley & Sons.

Comments

Popular posts from this blog

QTreeView and QTableView dynamic changes

C++ strings and string_view