As a program grows, it is usually necessary to access information from different parts of the code. We, as programmers, can do this in an efficient and flexible way by using pointers to reference information's address. If the value of a variable or object is changed, all dependencies that use this value will have access to the update value.
C++ has two groups of pointers: the raw and the smart pointer.
A pointer (called raw pointer after the implementation of smart pointers in C++11) is a type of variable that stores the address of another variable or object. The pointer can access their value by using their reference (their address).
We use two basic operations to handle a raw pointer:
* means “contents of”
& means “address of”
int value = 15; int *pointerValue; //The pointer variable pointerValue = &value; //Store address of value in the pointer variable cout << "Value of the variable: " << value << endl; cout << "Address stored in pointerValue: " << pointerValue << endl; cout << "Value of *pointerValue variable: " << *pointerValue << endl;
15 0x7ae8fa0b7c13 15
Notice that pointerValue has the address value of the variable 'value', so to access its value instead of its address we need to use an * (asterisk) before pointerValue.
We can also use pointers to refer to objects using the new and delete operators:
someClass* ptrClass = new someClass(); //Allocate the object ptrClass->getValue(); //Access a class member delete ptrClass ; //Delete the object
The new operator allocates some dynamic memory for the object. This piece of memory must be free after it’s used, which can be done using the delete operator.
What if the pointer is empty? In this case we have the nullptr. It means "the null pointer", used to represent the notion of 'no objects available'. It should be used instead of NULL (which was inherited from C).
One of the novelties of C ++ 11 was the implementation of smart pointers in the standard library. What is the main difference? Well, they use the RAII pattern when handling pointers:
“RAII guarantees that the resource is available to any function that may access the object. It also guarantees that all resources are released when the lifetime of their controlling object ends, in reverse order of acquisition.” (cppreference.com)
Unique_ptr - automatically erases everything it points to when it is destroyed. Can manage a single object or a dynamically-allocated array of objects. If it is not a constant object, it can transfer its ownership to another unique_ptr trough std::move.
Shared_ptr - is a smart pointer that keeps track of how many objects point to a particular feature and automatically erases the feature when no one is pointing at it. It meets the requirements of copy-constructible and copy-assignable.
Weak_ptr - is a pointer that does not have the property of the reference it points to. It can be used to store a way to access the underlying object of a shared_ptr without causing the reference count to be incremented. A good example of use is in cache development.
Auto_ptr - Removed in C++17. As seen in cppreference: “Copying an auto_ptr copies the pointer and transfers ownership to the destination: both copy construction and copy assignment of auto_ptr modify their right hand arguments, and the "copy" is not equal to the original.”