A smart pointer is a C++ class that manages a pointer to a dynamically allocated object. Unlike raw pointers, smart pointers can automatically release the dynamically allocated object when it is no longer required. Smart pointers help to manage the lifetime of dynamically allocated objects and reduce the risk of memory leaks.
C++11 introduced three main types of smart pointer, all of which are defined in the <memory> header provided by the Standard Library:
unique_ptr
A unique_ptr is a smart pointer that has exclusive ownership of an object. When the unique_ptr is destroyed, the object it owns is automatically destroyed. The owned object can also be explicitly released by calling reset().
A unique_ptr cannot be copied because there can only be one unique_ptr that owns the object. Ownership can, however, be transferred from one unique_ptr to another using std::move().
The following code section generates 3 unique smart pointers and initialises them. When the function goes out of scope the memory allocated to the pointers is freed.
#include <iostream>
#include <string.h>
#include <memory>
using namespace std;
void smartptr()
{
//smart pointer to int
std::shared_ptr <int> intPtr(new int );
//smart pointer to int array
std::shared_ptr <int> intarrayPtr(new int[100], std::default_delete<int[]>() );
// smart pointer to char array
std::shared_ptr <char> chararrayPtr(new char[100], std::default_delete<char[]>());
*intPtr=100;//set int value
intarrayPtr.get()[5]=5;//set int array value
strcpy(chararrayPtr.get(),"smart array");//set int char value
cout << "intPtr value: " << *intPtr<< endl;//out int value
cout << "intarrayPtr value: " << *(intarrayPtr.get()+5)<< endl;//out int array value
cout << "chararrayPtr value: " << (chararrayPtr.get())<< endl;//output int char value
}
int main()
{
smartptr();
//any attmempt to access the smart pointer values out of scope will fail
return 0;
}
shared_ptr
A shared_ptr is a smart pointer that allows multiple shared_ptr objects to share ownership of the same object. The object is automatically destroyed when the last shared_ptr owning it is destroyed or reset.
shared_ptr uses reference counting to keep track of how many shared_ptr objects currently own the same object. When the reference count reaches zero, the object is automatically destroyed.
#include <memory>
#include <iostream>
std::shared_ptr<int> func()
{
std::shared_ptr<int> valuePtr(new int(15));
return valuePtr; // no memory leak when smart pointer goes out of scope
}
int main()
{
std::shared_ptr <int> valuePtr1=func();
std::cout << *valuePtr1;
}
Although valuePtr is destroyed when func() returns, ownership of the dynamically allocated int has been transferred to valuePtr1. The object therefore remains available after the function has returned.
weak_ptr
A weak_ptr is created as a copy of shared_ptr. It provides access to an object but does not participate in reference counting and does not affect the shared_ptr or its other copies. Users can check the validity of the data by calling expired() or lock() functions.
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<int> sPtr(new int(15));//create and initiate shared smart pointer
std::cout << "shared pointer value is " << *sPtr << "\n";
std::weak_ptr <int> wPtr = sPtr;//set weak pointer to shared pointer
*sPtr = 10;//change value of shared pointer
std::cout << "weak pointer value is " << *wPtr.lock()<< "\n";//weak pointer does not change
sPtr.reset();//delete shared pointer
if (wPtr.expired())//check if weak pointer exists
{
std::cout << "weak pointer value has been deleted";
}
}
In addition to the smart pointers described above, earlier versions of C++ included std::auto_ptr. This smart pointer was deprecated in C++11 because of its problematic ownership behaviour and was removed from the C++17 standard. Modern C++ programs should use std::unique_ptr instead.