What are smart pointers?

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);
svg viewer

Implementation

#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 ptr
std::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);
svg viewer

Implementation

#include <iostream>
#include <memory>
using namespace std;
int main() {
// Valid, allocations
std::shared_ptr<int> p0(new int(24));
std::shared_ptr<int> p1(new int(20));
// Both pointer now point to same memory
std::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.

Implementation

#include <iostream>
#include <memory>
using namespace std;
int main() {
std::shared_ptr<int> p1(new int(23));
// make a weak pointer to p1
std::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 anything
if (p3) {
cout<<*p3<<endl;
}
else{
cout<<"p3 can't be printed since p1 no longer holds a memory"<<endl;
}
}

Copyright ©2024 Educative, Inc. All rights reserved