C++ Smart Pointers Learning

Introduction

Smart pointers seem to be used more and more widely. It’s necessary to remember them well.

shared_ptr

shared_ptr allows multiple pointers to point to the same object, while unique_ptr exclusively owns the object it points to.

Example:

#include <memory>
#include <thread>

class A
{
    char * str;
    public:
    A(){
        str = new char[20];
        printf("Constructor\n");
    }
    ~A()
    {
        printf("Destructor\n");
        delete [] str;
    }

};

std::shared_ptr<A> xixi;

void test()
{
    std::shared_ptr<A> shared_a = std::make_shared<A>();
    xixi = shared_a;
    printf("%d\n", xixi.use_count());
}

int main()
{   
    test();
    std::this_thread::sleep_for(std::chrono::seconds(1));
}

In the example above, xixi is a global smart pointer that will only release the object it points to when the program ends. If we remove xixi = shared_a, we would see the destructor being called before the delay in the main function.

unique_ptr

unique_ptr exclusively owns an object and can only be moved (std::move) between different unique_ptrs. There is no make_unique statement. You can only construct a unique_ptr by passing a pointer to an object in the constructor.

Use cases for unique_ptr:

  1. Providing exception safety guarantees for dynamically allocated resources Let’s look at the following code:
void Func()
{
    int *p = new int(5);

    // ...(may throw an exception)

    delete p;
}

This is our traditional approach: after we dynamically allocate memory, it’s possible that our subsequent code might not execute the delete operation due to an exception being thrown or early exit (if statement).

The solution is to use unique_ptr to manage dynamic memory. As long as the unique_ptr is successfully created, its destructor will be called, ensuring that dynamic resources are released.

void Func()
{
    unique_ptr<int> p(new int(5));

    // ...(may throw an exception)
}

weak_ptr

weak_ptr is also a powerful pointer, despite its name suggesting weakness. weak_ptr doesn’t control the lifecycle of an object and is used when you need to use an object without owning it. weak_ptr can be promoted to a shared_ptr if the object still exists.

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy