Codementor Events

Smart Pointers in C++ - Part 2

Published Jun 25, 2021Last updated Jun 27, 2021
Smart Pointers in C++ - Part 2

Introduction

Welcome to Part #2 of Smart Pointers in C++!

The Part #1 is a prerquisite for Part #2 and can be found here.

Let's learn some more about unique_ptr and also other types of smart pointers available in C++.

Some more usage scenarios for unique_ptr

Dynamically creating arrays with unique_ptr

We can create arrays with raw pointers like so.

int main() {
  int *arrPtr = new int[5];
  // creates an int array of size 5

  arrPtr[0] = 10;
    arrPtr[1] = 11;
    arrPtr[2] = 12;
    arrPtr[3] = 13;
    arrPtr[4] = 14;

  // work with the array
  for (int i = 0; i < 5; ++i)
    {
        std::cout << arrPtr[i] << '\n';
    }

  delete[] arr;
  // don't forget to free the memory
}

Using unique_ptr the code will be changed to

int main() {
    // arrays
    unique_ptr<int[]> arrPtr (new int[5]);
    // creates an int array of size 5

    arrPtr[0] = 10;
    arrPtr[1] = 11;
    arrPtr[2] = 12;
    arrPtr[3] = 13;
    arrPtr[4] = 14;

    // work with the array
    for (int i = 0; i < 5; ++i)
    {
        std::cout << arrPtr[i] << '\n';
    }
}

Again, we don't free the memory by using delete[]. That happens automatically as the unique_ptr takes ownership of the array.

Using move constructor

We already saw the use of move assignment in Part #1. Let's see how a move constructor can be used for unique_ptr.

/*
unique_ptr does not support copying. If one tries to copy a unique_ptr,
they'll get compiler error. However, it supports move semantics, where the
pointer is moved from one unique_ptr to another, which invalidates the
first unique_ptr
*/
unique_ptr<int> p1(new int(15));
unique_ptr<int> p1Now(std::move(p1));
std::cout << *p1Now; // 15

So we first created a new int, owned by p1, using a constructor. Then we move constructed p1Now to steal the memory owned by p1. This operation invlaidates p1. That's the reason we get 15 when we access the value owned by p1Now. Trying to access the value owned by p1 after p1Now is constructed, will result in runtime error.

Using arrow notations with smart pointers

We have seen that we can deference a smart pointer exactly the way we can dereference a raw pointer (using *). We can also use the arrow notation (->) on smart pointers just the way we use them on raw pointers.

unique_ptr<Person> personPtr (new Person("John Doe", 40));
std::cout << personPtr->getName() << '\n';
std::cout << "Age: " << personPtr->getAge() << '\n';

Some types of C++ Standard Library smart pointers

It is recommended to use the following smart pointers in favour of raw pointers when wrting C++ code.

  • unique_ptr
    As we have already seen, unique_ptr allows exactly one owner for a specific resource. This is the default choice for any resource unless one knows for sure that a shared_ptr is needed. Does not support copying, only move semantics are supported.
  • shared_ptr
    When we would like to have multiple smart pointers co-owning a resource, we have to use shared_ptr. These are reference-counted smart pointers (more about this later). The owned resources is not deleted until all owners have gone out of scope or have otherwise given up ownership.
  • weak_ptr
    This smart pointer can be used along with shared_ptr. It does not participate in reference counting. A weak_ptr can be used when we want access to an object but don't want the smart pointer to take ownership of the object.

Stay tuned for knowing more shared_ptr and weak_ptr.
Want to know more now? Follow the link

Discover and read more posts from Sandesh Patil
get started