Categories We Write About

Using std__make_unique and std__make_shared in C++

In C++, std::make_unique and std::make_shared are two factory functions introduced in C++14 and C++11, respectively, to simplify memory management and improve code safety and performance when using std::unique_ptr and std::shared_ptr.

1. std::make_unique

std::make_unique is used to create a std::unique_ptr, a smart pointer that owns a dynamically allocated object. std::unique_ptr ensures that there is only one owner of the resource, and the resource is automatically freed when the unique_ptr goes out of scope.

The primary advantage of using std::make_unique over manually creating a std::unique_ptr is that it eliminates the need for explicit new and provides better exception safety. Additionally, std::make_unique avoids unnecessary memory allocation for the control block (which would be used for reference counting) that std::shared_ptr might need.

Syntax:

cpp
std::unique_ptr<T> make_unique(Args&&... args);

Where:

  • T is the type of the object.

  • Args... are the arguments forwarded to the constructor of T.

Example:

cpp
#include <iostream> #include <memory> class MyClass { public: MyClass(int x) : x(x) {} void print() { std::cout << "Value: " << x << std::endl; } private: int x; }; int main() { // Creating a unique_ptr using std::make_unique std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>(10); ptr->print(); // Output: Value: 10 // Unique pointer goes out of scope here and the memory is automatically released }

2. std::make_shared

std::make_shared is used to create a std::shared_ptr, which is a smart pointer that manages a reference-counted object. Multiple shared_ptr instances can point to the same object, and the object is destroyed when the last shared_ptr pointing to it is destroyed or reset.

The advantage of using std::make_shared over manually creating a std::shared_ptr is that it performs the memory allocation for both the object and the control block (the reference counter) in a single allocation. This makes it more efficient compared to manually using new and std::shared_ptr together.

Syntax:

cpp
std::shared_ptr<T> make_shared(Args&&... args);

Where:

  • T is the type of the object.

  • Args... are the arguments forwarded to the constructor of T.

Example:

cpp
#include <iostream> #include <memory> class MyClass { public: MyClass(int x) : x(x) {} void print() { std::cout << "Value: " << x << std::endl; } private: int x; }; int main() { // Creating a shared_ptr using std::make_shared std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>(20); ptr->print(); // Output: Value: 20 // Shared pointer goes out of scope here, but memory is not freed until the last reference is destroyed. }

Comparison Between std::make_unique and std::make_shared

Featurestd::make_uniquestd::make_shared
OwnershipUnique ownership (only one owner)Shared ownership (multiple owners)
Memory AllocationOnly allocates memory for the objectAllocates memory for both the object and reference counter
Use CaseWhen you need exclusive ownership of a resourceWhen you need shared ownership or shared resource management
Control Block (Reference Count)No control block, just the objectControl block (reference counter) is used
PerformanceMore efficient as it only allocates memory for the objectSlightly less efficient due to the reference counter allocation

Best Practices

  • Use std::make_unique: When you need a single owner of a resource, and you don’t need shared ownership. It avoids unnecessary overhead and makes ownership semantics clear.

  • Use std::make_shared: When multiple owners may share access to a resource, and you need reference counting. It is more efficient than using new with std::shared_ptr because of the single memory allocation for both the object and the reference count.

Potential Pitfalls

  1. Circular references with std::shared_ptr: When using std::shared_ptr, it’s essential to be cautious of circular references. If two or more objects share shared_ptrs that point to each other, the reference count will never reach zero, causing a memory leak. You can solve this by using std::weak_ptr for breaking cycles.

  2. Exception Safety: Both std::make_unique and std::make_shared provide better exception safety than using new and manually managing smart pointers. In the case of an exception, memory allocated for the object will be properly freed without needing to explicitly manage it.

In conclusion, std::make_unique and std::make_shared are powerful tools for modern C++ memory management. They make code cleaner, safer, and more efficient by eliminating the need for manual memory management, and they are highly recommended for managing dynamic memory in C++ programs.

Share This Page:

Enter your email below to join The Palos Publishing Company Email List

We respect your email privacy

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Categories We Write About