Pointers & Smart Pointers
Thomas J. Kennedy
You have worked with pointers at least once. Even if you managed to skip pointers in your previous programming courses… you had to work with pointers on the first assignment this semester.
1 Pointers
So far you have seen raw pointers used for a few things. This semester we have used pointers to build arrays.
double* aBigArray = new double[1000];
//...
// Pretend there is more code here
//...
delete[] aBigArray;
We have also used pointers to build linked lists by allocating nodes in a push_back
or append
function.
void LinkedList::appendNode(int to_add)
{
Node* new_node = new Node(to_add);
// Handle the case where the first node is added
if (this->head == nullptr) {
this->head = new_node;
this->tail = new_node;
}
else {
(this->tail)->next = new_node;
this->tail = new_node;
}
// Increase the number of nodes
this->nodes++;
}
We made sure all nodes were deallocated in a Destructor.
LinkedList::~LinkedList()
{
Node* this_iterator = this->head;
while (this_iterator != nullptr) {
Node* to_delete = this_iterator;
// move to next node
this_iterator = this_iterator->next;
// delete the current node
delete to_delete;
}
}
If we are building a data structure (e.g., a linked list or an array). Raw pointers are unavoidable.
2 Smart Pointers
What if we are working in high-level code? Suppose we are allocating a new Cookbook
object in a main function.
int main(int argc, char** argv)
{
Cookbook* aCookbookPtr = new Cookbook();
//...
// Pretend something fun happens here.
//...
return 0;
}
Oops! We forgot to deallocate the Cookbook
with delete aCookbookPrt;
at the end of main
. Now we have a memory leak (which you should remember from Assignment 1).
Modern C++ (i.e., C++14 and newer) provides a collection of smart pointers and associated helper functions. Take a quick look at https://en.cppreference.com/w/cpp/memory. There are quite a few things listed. For now we will focus on:
-
std::auto_ptr
- Do not use this. It was deprecated in C++17. -
std::unique_ptr
- A pointer that guarantees unique ownership. This pointer can not be copied (the compiler will yell at you). When this pointer leaves scope (i.e., its destructor is called)delete
is called automatically. -
std::shared_ptr
- A pointer that keeps track of the number of copies (using a reference count). Once the count hits zero…delete
is called automatically.
3 Unique Ownership
If we revisit the Cookbook
example… we probably only want one pointer to the aCookbookPtr
. A std::unique_ptr
is definitely what we want to use.
int main(int argc, char** argv)
{
std::unique_ptr<Cookbook> aCookbookPtr(new Cookbook());
//...
// Pretend something fun happens here.
//...
return 0;
}
However, we should probably replace
std::unique_ptr<Cookbook> aCookbookPtr(new Cookbook());
with
std::unique_ptr<Cookbook> aCookbookPtr = std::make_unique<Cookbook>();
Since we know what type we have… auto
is probably useful here.
auto aCookbookPtr = std::make_unique<Cookbook>();
Considering how I tend to avoid auto
… that is unexpected.
4 The Other Types of Pointers
We will see smart pointers again… in the C++ Shapes Example.