The Palos Publishing Company

Follow Us On The X Platform @PalosPublishing
Categories We Write About

How to Use std__make_shared and std__make_unique in C++

In C++, std::make_shared and std::make_unique are utility functions used to create smart pointers (std::shared_ptr and std::unique_ptr respectively). These functions offer a safer and more efficient way to allocate memory and manage the lifecycle of objects, compared to using new directly. Here’s how they work:

1. std::make_shared

std::make_shared creates a std::shared_ptr to manage an object on the heap. It ensures that the object is properly destroyed when no more shared_ptr objects point to it. Additionally, std::make_shared performs a single memory allocation to store both the object and the control block (which contains reference counts). This can be more efficient than using new with std::shared_ptr because it avoids an additional memory allocation for the control block.

Syntax:

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

Where T is the type of the object, and Args&&... args are the constructor arguments for the object.

Example:

cpp
#include <iostream> #include <memory> class MyClass { public: MyClass(int x) : value(x) { std::cout << "MyClass constructor: " << value << std::endl; } void display() { std::cout << "Value: " << value << std::endl; } private: int value; }; int main() { // Creating a shared pointer to MyClass with value 10 std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>(10); // Accessing the object through the shared pointer ptr->display(); // Shared pointer will automatically delete the object when it goes out of scope return 0; }

Advantages of std::make_shared:

  • Efficient: It combines the memory allocation for the object and the control block.

  • Safer: It ensures that the memory is automatically freed when no shared_ptr is referring to the object.

2. std::make_unique

std::make_unique creates a std::unique_ptr, which is a smart pointer that manages a dynamically allocated object, but it does not allow ownership to be shared (i.e., it enforces unique ownership). It’s typically used when you want the object to be destroyed when the unique_ptr goes out of scope, and you don’t need shared ownership.

Syntax:

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

Where T is the type of the object, and Args&&... args are the constructor arguments for the object.

Example:

cpp
#include <iostream> #include <memory> class MyClass { public: MyClass(int x) : value(x) { std::cout << "MyClass constructor: " << value << std::endl; } void display() { std::cout << "Value: " << value << std::endl; } private: int value; }; int main() { // Creating a unique pointer to MyClass with value 20 std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>(20); // Accessing the object through the unique pointer ptr->display(); // Unique pointer will automatically delete the object when it goes out of scope return 0; }

Advantages of std::make_unique:

  • Ensures exclusive ownership: A unique_ptr cannot be copied, but it can be moved.

  • Prevents potential memory leaks that may occur if an object is forgotten or improperly deleted.

  • More efficient: It only allocates memory for the object, not for a control block as std::shared_ptr does.

Key Differences Between std::shared_ptr and std::unique_ptr:

  • Ownership Model:

    • std::shared_ptr: Shared ownership, meaning multiple shared_ptr objects can point to the same object.

    • std::unique_ptr: Exclusive ownership, meaning only one unique_ptr can own the object at a time.

  • Reference Counting:

    • std::shared_ptr uses reference counting to manage the object’s lifecycle. The object is destroyed when the last shared_ptr goes out of scope or is reset.

    • std::unique_ptr has no reference counting and destroys the object when it goes out of scope.

  • Memory Management:

    • std::shared_ptr is typically heavier due to the reference count stored in a separate control block.

    • std::unique_ptr is lighter since it only holds the object’s memory.

When to Use std::make_shared and std::make_unique:

  • Use std::make_shared when:

    • You need shared ownership.

    • You want to avoid manual memory management and take advantage of automatic destruction when the last reference to the object goes out of scope.

  • Use std::make_unique when:

    • You need unique ownership.

    • You want to ensure that there’s only one owner of the object, and you don’t need shared ownership.

General Best Practices:

  • Prefer std::make_unique when possible, as it is simpler, more efficient, and avoids the overhead of reference counting.

  • Use std::make_shared when you need shared ownership, but remember it introduces some overhead due to the reference count.

By using these helper functions, you ensure that your objects are managed automatically and that memory is correctly released without the need for manual cleanup.

Share this Page your favorite way: Click any app below to share.

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

We respect your email privacy

Categories We Write About