Standard library included with C++ compilers provides some specific resource management pointers classes which are also called as Smart Pointers.
A normal (raw) pointer typically points to an object, but it doesn’t indicate who owns the objects. This leads to the confusion most of the times, that who is supposed to delete the pointer and free the memory.
Also, by looking into the pointer, one can’t guess how the pointer should be deleted.
Smart pointers are designed to overcome these shortcomings of raw pointers.
Types of Smart Pointers
- unique_ptr -> This pointer class has the exclusive ownership.
- shared_ptr -> This pointer class has the shared ownership.
- weak_ptr -> This pointer class is used with shared_ptr and it doesn’t have any ownership. This pointer is typically used to break loops into circular data structures.
unique_ptr
The unique_ptr has following properties:
- A unique_ptr owns the object it points to, which means destroying the object is unique_ptr’s responsibility.
- A unique_ptr can’t be copied but it can be moved. This is because in case of copy, ownership needs to be shared which can’t be possible with unique_ptr.
- A unique_ptr destroys the object by calling its destructor when it is itself getting destroyed.
- A unique_ptr also provides exception safety for dynamically allocated object.
shared_ptr
The shared_ptr has following properties:
- A shared_ptr has the shared ownership of the object it points to.
- Typically, it is being used when two or more pieces of code requires access to some data but neither of them could have exclusive ownership.
- A shared_ptr internally maintains a reference count which indicates ownership is shared between how many entities. The object will be deleted when reference count reduces to 0.
- Usage of shared_ptr could create a circular linked structure of data which could lead to resource leak. Hence, usage of shared_ptr should be well thought of.
- shared_ptr is typically slower than unique_ptr.
- Its size is of two pointers, one for object and one for reference counting. Hence, it uses more memory than unique_ptr.
weak_ptr
A weak_ptr could refer to an object managed by a shared_ptr. The weak_ptr has following properties:
- A weak_ptr allows access to an object which is owned by someone else.
- An object pointed by weak_ptr could be deleted any point of time as it doesn’t have ownership.
- A weak_ptr typically used in to break the loop in circular data structure managed by shared_ptrs.
Let’s have a look into the example which illustrates the usage of smart pointers.
#include <iostream>
#include <memory>
using namespace std;
int main ()
{
int* x = new int(10);
int* y = new int(20);
int* z = NULL;
unique_ptr<int> p = (unique_ptr<int>)(new int(10));
cout << "1st " << x << " " << *p << endl;
unique_ptr<int> q = move (p);
cout << "2nd " << x << " " << " " << *q << " " << p.release () << endl;
if (q)
cout << "3rd " << x << " " << " " << *q << " " << endl;
z = q.release ();
if (q)
cout << "4th " << x << " " << " " << *q << " " << endl;
if (z)
cout << "5th " << z << " " << " " << *z << " " << endl;
shared_ptr<int> s1 = shared_ptr<int> (new int(20));
cout << s1.use_count () << endl;
shared_ptr<int> s2 = s1;
cout << s1.use_count () << " " << s2.use_count () << endl;
s1.reset ();
cout << s1.use_count () << " " << s2.use_count () << endl;
weak_ptr<int> w1 = s2;
cout << s1.use_count () << " " << s2.use_count () << " " << w1.use_count () << endl;
}
Let’s look into the output of above sample program.
1st 0xa59010 10
2nd 0xa59010 10 0
3rd 0xa59010 10
5th 0xa59050 10
1
2 2
0 1
0 1 1