What is a smart pointer in C++?

To understand the need for smart pointers, it’s important to first understand the shortcomings of raw pointers.

Raw pointers

Raw pointers are used (among other things) to access heap memory that has been allocated using the new operator and deallocated using the delete operator.

However, if the memory is not properly deallocated, it can lead to memory leaks. This is where smart pointers come in. The purpose of smart pointers is to manage dynamically allocated memory automatically so that programmers don’t have to worry about memory leaks in large code bases or complex data structure implementations.

Motivation

To better understand the difficulty of working with raw pointers, let’s take a look at the following example. The code dynamically allocates three integers on the heap (a, b, and c), and then sets c to the sum of a and b.

int* heapSum()
{
int* a = new int{1};
if(a == nullptr)
{
return nullptr;
}
int* b = new int{2};
if(b == nullptr)
{
//Allocation for b failed, free a
delete a;
return nullptr;
}
int* c = new int{3};
if(c == nullptr)
{
//Allocation for c failed, free a and b
delete a;
delete b;
return nullptr;
}
*c = *a + *b;
//Free a and b as they are no longer needed
delete a;
delete b;
return c;
}

This example is significant because it shows that even in a simple function like adding three numbers, it can become complex to handle allocation failures properly. For instance, if c allocation fails, we must free both a and b, which were successfully allocated earlier (lines 21 and 22).

Idea for a solution

Using local variables allocated on the stack results in simpler code that doesn’t risk memory leaks. There’s no need to manually deallocate stack variables as their lifetime is automatically managed by the compiler. See below:

int stackSum()
{
    int a = 1;
    int b = 2;
    int c = a + b;
    return c;
}

We will leverage this automatic lifetime management of stack variables together with OOP concepts such as constructors and destructors to implement smart pointers.

Enter smart pointers

The smart pointer paradigm is based on RAII (Resource Acquisition Is Initialization) and uses the above idea. We wrap the heap memory allocation in an object allocated on the stack. The constructor allocates memory, and the destructor deallocates it when the object is no longer needed, ensuring the memory is freed.

#include <iostream>
class SmartIntPointer
{
private:
int* rawPointer = nullptr;
public:
SmartIntPointer(int value)
{
std::cout << "SmartIntPointer constructor, allocating memory" << std::endl;
rawPointer = new int{value};
}
~SmartIntPointer()
{
std::cout << "SmartIntPointer destructor, freeing memory" << std::endl;
delete rawPointer;
}
int& operator*() const
{
return *rawPointer;
}
};
int main()
{
SmartIntPointer sp(5);
std::cout << *sp << std::endl;
*sp = 6;
std::cout << *sp << std::endl;
return 0;
}

The above code demonstrates how smart pointers work:

  • Line 9: The constructor allocates memory for the raw pointer and initializes it with the provided value.
  • Line 15: The destructor frees the allocated memory.
  • Line 21: We overload the * operator to provide access to the raw pointer. This operator returns a reference so we can read and write to the smart pointer as if it were a raw pointer.

The code output shows that the constructor runs when the object is created, allocating memory. We can access the underlying raw pointer using the * operator, and when the program ends, the destructor runs and frees the memory.

Further study

C++ provides built-in smart pointer implementations, such as std::unique_ptr, std::shared_ptr, and std::weak_ptr, which work with any data type, including arrays. The above example provides a simplified version of how smart pointers work, and there are other considerations to be aware of when working with them, which we can see with the built-in smart pointers.

To learn how to write good pointer-intensive code with raw pointers, visit this course for further information and practical exercises.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved