Pointers & Smart Pointers

Thomas J. Kennedy

Contents:

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:

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.