Smart Pointers in C++: std::unique_ptr, std::shared_ptr, and std::weak_ptr
Smart pointers in the C++ programming language are class program parameter variable objects that manage and hold the lifetime of dynamically allocated object memory (or any other useful program resource) in a user-defined class program. Smart pointers manage and control the proper order of deallocation of C++ object system resources when they are no longer needed in the current program. Smart pointers in C++ are a built-in feature of the C++ Standard Library, first introduced in version C++11. Smart pointers help C++ users avoid common memory management mistakes such as memory leaks and dangling pointers.

There are three main types of smart pointers in C++ programming.
- std::unique_ptr
- std::shared_ptr
- std::weak_ptr
So, let’s explore each smart pointer in C++ programming in detail.
std::unique_ptr overview in C++.
- Ownership – In a C++ program, std::unique_ptr is a smart pointer object method that holds a single ownership value of a program resource. When a unique_ptr goes out of scope, it automatically deletes the program resource it points to.
- Transfer Ownership – In a C++ program, the default ownership of the program parameter object managed and controlled by std::unique_ptr can be transferred using move semantics (e.g., the std::move method).
- Non-copyable – In a C++ program, a std::unique_ptr smart pointer cannot be copied within the current program; these smart pointers can only be moved when needed. This ensures that a program only defines a single owner of a smart pointer resource at any given time, preventing accidental double deletion of allocated memory.
Syntax of the std::unique_ptr smart pointer.
#include <memory>
std::unique_ptr<T> ptrone(new T()); // Here, create a smart pointer unique_ptr with the new keyword.
std::unique_ptr<T> ptrtwo = std::make_unique<T>(); // Here, a basic method for creating ptrtwo.
Example of a std::unique_ptr smart pointer.
#include <iostream>
#include <memory> // Here we use the memory header file for the smart pointer memory object.
class SampleClass {
public:
SampleClass() { std::cout << “SampleClass Constructor created \n”; }
~SampleClass() { std::cout << “SampleClass Destructor created \n”; }
};
int main() {
std::unique_ptr<SampleClass> ptrone = std::make_unique<SampleClass>(); //here we allocated memory for SampleClass
// here we transferred ownership, ptrone is now nullptr value
std::unique_ptr<SampleClass> ptrtwo = std::move(ptrone);
// here ptrone is now nullptr value, but ptrtwo still owns the memory value object.
return 0; // here destructor for SampleClass will be automatically called when ptrtwo goes out of its scope.
}
Special features of the std::unique_ptr smart pointer.
- Automatic deletion – When std::unique_ptr goes out of scope in a C++ program. This automatically deallocates the associated memory object.
- No copy semantics – Remember that std::unique_ptr smart pointers cannot be copied in a C++ program. However, they can be moved using the std::move method.
- Efficient – Because a smart pointer maintains single ownership within a program, there is no reference counting overhead.
- Use Case – In a C++ program, a smart pointer is ideal for managing and controlling system program resources that have clear, single ownership, such as dynamically allocated object values in a user-defined class.
std::shared_ptr overview in C++.
- Ownership – In a C++ program, a std::shared_ptr smart pointer provides shared ownership permissions for a program memory resource. Where more than one shared_ptr smart pointer can manage and control the same system resource. These smart pointer program resources are destroyed only when the last shared_ptr owned by these smart pointers is destroyed or reset.
- Reference Counting – The std::shared_ptr smart pointer in a C++ program uses the program reference counting method to keep track of how many shared_ptr instances are managing and controlling the same parameter variable object in the current program. When its reference count reaches zero, the allocated object is deleted.
Syntax of std::shared_ptr smart pointer.
#include <memory>
std::shared_ptr<T> ptrone = std::make_shared<T>(); // Here is the method to create a smart pointer
std::shared_ptr<T> ptrtwo(new T); // Here is the smart pointer direct initialization method
Instance of a std::shared_ptr smart pointer.
#include <iostream>
#include <memory>
class SampleClass {
Public:
SampleClass() { std::cout << “SampleClass Constructor created \n”; }
~SampleClass() { std::cout << “SampleClass Destructor created \n”; }
};
int main() {
std::shared_ptr<SampleClass> ptrone = std::make_shared<SampleClass>(); // Here we use Reference 1
{
std::shared_ptr<SampleClass> ptrtwo = ptrone; // Here we use Reference 2
std::cout << “Internal inner scope is \n”;
} // ptrtwo goes out of scope, reference 1
std::cout << “External inner scope is \n”;
return 0; // Here we use the destructor for SampleClass, when the last shared_ptr goes out of its scope.
}
Special features of the std::shared_ptr smart pointer.
- Reference counting – This keeps track, from within a C++ program, of how many shared_ptr smart pointer instances share ownership of a resource. When the last shared_ptr smart pointer terminates, the objects stored in it are automatically deleted.
- Thread-safe – Reference counting in C++ programs is a thread-safe method, meaning that multiple threads can manage the same program resources in a secure order.
- Overhead – Due to reference counting in C++ programs, std::shared_ptr incurs a slight performance overhead compared to the std::unique_ptr smart pointer.
- Use Case – In C++ programs, shared_ptr is the best choice for particular situations where multiple parts of the program source code require shared access to a resource.
std::weak_ptr overview in C++.
- Non-owning Reference – In a C++ program, a std::weak_ptr smart pointer does not own the resource. This smart pointer is used to refer to the class program object managed by std::shared_ptr without affecting its reference count.
- Prevents Circular References – In a C++ program, the std::weak_ptr smart pointer is particularly useful for breaking circular references that may be defined between shared_ptrs. A circular reference in a smart pointer occurs when two or more shared_ptr smart pointers reference each other, causing the smart pointer reference count to never reach zero, resulting in a memory leak in the current C++ program.
- Expired Resources – If an object resource managed by a std::shared_ptr in the current C++ program is deleted (because its last owner has gone out of the shared_ptr scope), the std::weak_ptr smart pointer becomes “expired.” And now it cannot be used to access the class program object.
Syntax std::weak_ptr smart pointer.
#include <memory>
std::weak_ptr<T> weak_ptr = shared_ptr_instance; // This represents a shared_ptr
Example of std::weak_ptr smart pointer.
#include <iostream>
#include <memory>
class SampleClass {
public:
SampleClass() { std::cout << “SampleClass Constructor created \n”; }
~SampleClass() { std::cout << “SampleClass Destructor created \n”; }
};
int main() {
std::shared_ptr<SampleClass> sharedPtr = std::make_shared<SampleClass>();
std::weak_ptr<SampleClass> weakPtr = sharedPtr; // here we define weak reference to sharedPtr
if (auto temp = weakPtr.lock()) { // here it convert weak_ptr to shared_ptr class object
std::cout << “Smart pointer resource is working \n”;
} else {
std::cout << “Smart pointer resource deleted \n”;
}
sharedPtr.reset(); // here it reset the sharedPtr, causing SampleClass to be deleted here
if (auto temp = weakPtr.lock()) { // here it checks if resource is still available or not
std::cout << “Smart pointer resource is working \n”;
} else {
std::cout << “Smart pointer resource deleted \n”; // here this information will be printed
}
return 0;
}
Special features of the std::weak_ptr smart pointer.
- Non-owning – In a C++ program, a weak_ptr does not affect the reference count of the shared_ptr it references.
- Expired State – In a C++ program, a weak_ptr can be locked (e.g., converted to a shared_ptr) to check whether the class object is still working or alive in the current program. If the current class object is deleted (e.g., the reference count reaches zero), this lock will return a nullptr value.
- Avoid circular references – In C++ programs, this is mostly used to avoid circular dependencies between shared_ptr instances. This prevents a single class object reference from increasing its reference count.
- Use Cases − The weak_ptr method is an ideal choice in C++ programs for caching, the observer pattern, and breaking circular references in structures such as graphs.

