make_shared vs shared_ptr constructor
(If you don’t know what are smart pointers, read the following post first!)
One can create a shared_ptr object either via its constructors or through make_shared call from std.
But what are the differences? Which one we should use?
Let’s first talk about shared_ptr.
What is shared_ptr?
Shared ptr is a wrapper over a pointer. The difference between it and unique_ptr is that shared_ptr can share the ownership (multiple shared_ptr towards the same pointer).
It’s based on reference count, which is incremented when we copy the shared_ptr, and decremented when the shared_ptr is going out of scope.
When the ref count reaches 0, the pointer contained in shared_ptr is also destroyed.
In order for this to work, we have the following relation between objects:
– contains the object (pointer)
– contains the ref count structure
– points towards the ref count structure
=> Can interogate the shared_ptr status. In case the ref count is bigger than 0 (there’s still a valid shared_ptr), it can be converted to the shared_ptr containing the object.
ref count structure
– count the shared_ptr pointing to the object
– count the weak_ptr pointing to this
How can we allocate a shared_ptr object?
1) Separate allocations
Data* ptr = new Data;
We can see that we have two memory allocations. first one is for the object itself, while second one creates only the ref count structure on the heap.
2) Single allocation
std::shared_ptr<Data> shared = std::make_shared<Data>();
Using make_shared, both the object and the ref count structure are allocated into one single call. This way, the ref count structure contains the object directly, instead of just pointing to it.
So, what are the differences?
Since there are two separate allocations, each of them can be deallocated separatelly. This way, the data can be destroyed when shared_count reaches 0, even if there’s still a weak_ptr pointing to the structure.
Single allocation: The lifetime of the object is DIRECTLY influenced by the ref count structure. Since the object was allocated in the same place, its lifetime will be over when the ref count structure is destroyed. Because weak_ptr points towards it and needs to interogate the status, as long as we still have a weak_count pointing to it, the object WILL NOT be deleted.