Effective Modern C++ (page 136) uses the following example to motivate std::weak_ptr
. A cache is defined as an unordered map with weak pointers to objects as values. Whenever clients of this cache request an object (by key), the corresponding weak pointer is looked up and lock()
is invoked on it. If the resulting std::shared_ptr
is not null
, it is returned. Otherwise, the object is re-loaded from an external database, entered into the cache and std::shared_ptr
to it is returned.
Now the question: one might think that it would be possible to implement this without std::weak_ptr
, but to store strong shared pointers as cache values instead. If use_count()
of a strong pointer is equal to one, that means that all the client's pointers have been destroyed. Is the whole point of this example that using std::weak_ptr
allows us to save memory by actually deleting the objects?
Note that the control block used by std::weak_ptr and std::shared_ptr is thread-safe: different non-atomic std::weak_ptr objects can be accessed using mutable operations, such as operator= or reset , simultaneously by multiple threads, even when these instances are copies or otherwise share the same control block ...
Shared pointers in C++ In C++, a shared pointer is one of the smart pointers. The shared pointer maintains a reference count which is incremented when another shared pointer points to the same object. So, when the reference count is equal to zero (i.e., no pointer points to this object), the object is destroyed.
"Shared pointer is a smart pointer (a C++ object wih overloaded operator*() and operator->()) that keeps a pointer to an object and a pointer to a shared reference count. Every time a copy of the smart pointer is made using the copy constructor, the reference count is incremented.
The smart pointer has an internal counter which is decreased each time that a std::shared_ptr , pointing to the same resource, goes out of scope – this technique is called reference counting. When the last shared pointer is destroyed, the counter goes to zero, and the memory is deallocated.
"Is the whole point of this example that using std::weak_ptr allows us to save memory by actually deleting the objects?"
Yes. Otherwise, the cache would keep the pointed-to resources allocated indefinitely. The space required for a control block, if allocated separately, is generally much less than the sort of resource that might require caching (e.g. textures, mesh data, even localized strings).
While it is possible to implement the same functionality using atomics and checking for a reference count of 1, this would require a custom handle implementation. std::weak_ptr
and std::shared_ptr
make the whole thing much less of an ordeal to prototype.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With