Shared and Weak Pointers: Subtle Connections
Nikolai Kutiavin
C++ Applications and Tools Developer | Software Framework Development | Delivered high-quality, well-tested code to engineering teams
Due to the reference counting mechanism, shared pointers are prone to forming reference circles which can lead to memory leaks. To address this problem, shared pointers have a counterpart - weak pointers.
Let's consider an implementation of the listener pattern. There is an ?????????????????????? class that produces events and a ???????????????? class that consumes those events. When an event is raised, the listener gets notified through the ????????????????::????????????() method and should pull updates from ?????????????????????? using the ??????????????????????::????????????????????() method.
The dependency between these two classes can be represented in the following diagram:
In this setup, the objects form a typical reference circle. If only shared pointers are used, the memory cannot be deallocated, even when there are no external references. To prevent this, ?????????????????????? holds a shared pointer to listeners, while ???????????????? holds only a weak pointer to ??????????????????????.
class EventSource {
public:
std::vector<std::string> getUpdates() const;
private:
std::vector<std::shared_ptr<Listener>> m_listeners;
};
class Listener {
public:
Listener(std::weak_ptr<EventSource> source);
virtual void notify() = 0;
protected:
std::weak_ptr<EventSource> getSource();
private:
std::weak_ptr<EventSource> m_source;
};
Creating a new copy of ??????::????????_?????? does not increase the reference count. When you need actual access to the object, a ??????::????????????_?????? should be obtained, as shown in a possible implementation of ????????????????::????????????():
void ConcreteListener::notify() {
std::shared_ptr<EventSource> source = getSource().lock();
if (!source) {
return;
}
auto updates = source->getUpdates();
// ...
}
To obtain a shared pointer from a weak pointer, follow these steps: