A smart pointer is a composition class designed to manage dynamically allocated memory and to ensure that the memory gets deleted when the smart pointer object goes out of scope.
Smart pointers are just classes that wrap the raw pointer and overload the ->
and *
operators; this allows them to offer the same syntax as a raw pointer.
C++11 has three types of smart pointers that are defined in the <memory>
header of the Standard Library. They are:
std::unique_ptr
std::shared_ptr
std::weak_ptr
unique_ptr
An unique_ptr
has exclusive ownership of the object it points to and will destroy the object when the pointer goes out of scope. A unique_ptr
explicitly prevents copying of its contained pointer. Instead, the std::move
function has to be used to transfer ownership of the contained pointer to another unique_ptr
.
The syntax to declare a unique pointer is :
std::unique_ptr<Type> p(new Type);
#include <memory>#include <iostream>using namespace std;void print_value(std::unique_ptr<int> p) {cout<< *p << endl;}int main(){std::unique_ptr<int> ptr(new int(24));// The following line will result in ERROR since// we are not allowed to copy a unique ptrstd::unique_ptr<int> ptr_copy = ptr;// The following code needs to be used to copy// the pointer.std::unique_ptr<int> ptr_copy = std::move(ptr);// The following line will result in ERROR since// arguments are passed by value(copy) to function.print_value(ptr);}
shared_ptr
A std::shared_ptr
owns the object it points to but, unlike the unique_ptr
, it allows for multiple references. The smart pointer has an internal counter which is decreased each time that a std::shared_ptr
, pointing to the same resource, goes out of scope – this technique is called reference counting. When the last shared pointer is destroyed, the counter goes to zero, and the memory is deallocated.
The syntax to declare a shared pointer is :
std::shared_ptr<Type> p(new Type);
#include <iostream>#include <memory>using namespace std;int main() {// Valid, allocationsstd::shared_ptr<int> p0(new int(24));std::shared_ptr<int> p1(new int(20));// Both pointer now point to same memorystd::shared_ptr<int> p2 = p1;p1.reset();// p2 still points to the memory and hence can print it.cout<<*p2<<endl;// Deletes the memory, since no one else owns the memory.p2.reset();}
weak_ptr
A std::weak_ptr
is like a std::shared_ptr
except that
it doesn’t increase its reference count. It is defined as a smart pointer that holds a non-owning (weak) reference to an object that is managed by another std::shared_ptr
.
The syntax to declare a weak pointer is :
std::weak_ptr<int> p_weak1(p_shared);
The shared_ptr
holds the real object, whereas the weak_ptr
uses a lock
to connect to the real owner and returns NULL otherwise.
#include <iostream>#include <memory>using namespace std;int main() {std::shared_ptr<int> p1(new int(23));// make a weak pointer to p1std::weak_ptr<int> wp1 {p1};{std::shared_ptr<int> p2 = wp1.lock(); // Now p1 and p2 own the memory.if (p2) {cout<<*p2<<endl;}}// p2 gets destroyed since out of scope.// only p1 holds the memory now// Delete p1.p1.reset();std::shared_ptr<int> p3 = wp1.lock();// code will not execute since p3 doesn't point to anythingif (p3) {cout<<*p3<<endl;}else{cout<<"p3 can't be printed since p1 no longer holds a memory"<<endl;}}