Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

weak_ptr, make_shared and memory deallocation

A control block of a shared_ptr is kept alive while there is at least one weak_ptr present. If the shared pointer was created with make_shared that implies that the whole memory of the object is kept allocated. (The object itself is properly destructed, but since the control block and the memory for the object were allocated in one chunk, as make_shared does, they can only be deallocated together.)

Is my understanding correct?

It seems that this behaviour represents a problem, for example in the famous "cache example". The memory for the objects will be kept allocated forever.

It it a problem in any practical situations? Shall the shared_ptr be created using a constructor in such a situation (large object and intent to use weak_ptrs)?

like image 624
Ilya Popov Avatar asked Aug 20 '15 08:08

Ilya Popov


People also ask

What is the difference between shared_ptr and Weak_ptr?

The only difference between weak_ptr and shared_ptr is that the weak_ptr allows the reference counter object to be kept after the actual object was freed. As a result, if you keep a lot of shared_ptr in a std::set the actual objects will occupy a lot of memory if they are big enough.

What is the use of Make_shared?

make_shared is exception-safe. It uses the same call to allocate the memory for the control block and the resource, which reduces the construction overhead. If you don't use make_shared , then you have to use an explicit new expression to create the object before you pass it to the shared_ptr constructor.

Why is Make_shared more efficient?

One reason is because make_shared allocates the reference count together with the object to be managed in the same block of memory. OK, I got the point. This is of course more efficient than two separate allocation operations.

Why do we need Weak_ptr?

By using a weak_ptr , you can create a shared_ptr that joins to an existing set of related instances, but only if the underlying memory resource is still valid. A weak_ptr itself does not participate in the reference counting, and therefore, it cannot prevent the reference count from going to zero.


2 Answers

Is my understanding correct?

Yes. If your weak_ptrs significantly outlive the (large) object and you are tight on memory, it may be beneficial to avoid make_shared.

However, "large" here is measured by sizeof, and many conceptually "large" objects (for example, most standard containers, except std::array) are quite small by that metric, because they allocate additional memory to store their contents, which will be freed as soon as the object is destroyed.

like image 110
T.C. Avatar answered Oct 20 '22 14:10

T.C.


I tried this in VS2013 and you're completely correct. The destructor is called when the last shared_ptr is destroyed, so any other objects or memory associated with the object will be destroyed, but if the shared_ptr is created with make_shared the memory is never destroyed until the last weak_ptr is.

I think it's always good to clean up or reset your weak_ptrs if lock() fails because even without make_shared it's still using some memory.

like image 3
Dave Emberton Avatar answered Oct 20 '22 14:10

Dave Emberton