← Patterns

Weak reference

12345678910111213141516171819202122232425262728293031323334#include <memory> class bar; class foo { public: foo(const std::shared_ptr<bar>& b) : forward_reference{b} { } private: std::shared_ptr<bar> forward_reference; }; class bar { public: void set_back_reference(const std::weak_ptr<foo>& f) { this->back_reference = f; } void do_something() { std::shared_ptr<foo> shared_back_reference = this->back_reference.lock(); if (shared_back_reference) { // Use *shared_back_reference } } private: std::weak_ptr<foo> back_reference; };

This pattern is licensed under the CC0 Public Domain Dedication.

Requires c++11 or newer.

Intent

Maintain a non-owning reference to a shared dynamically allocated object to break circular dependencies.

Description

The std::weak_ptr type represents a non-owning reference to dynamically allocated object with shared ownership (std::shared_ptr). As they do not contribute to the reference count of the managed object they refer to, the object can be destroyed at any time when all std::shared_ptrs give up ownership. However, a std::weak_ptr can be converted to a std::shared_ptr to provide temporary ownership and safe access to the object.

In the example code, we have two classes: foo on lines 5–14, and bar on lines 16–30. A foo object has shared ownership of a bar (line 13), and bar requires some form of reference back to the foo that owns it. If this back reference were a std::shared_ptr<foo>, it would introduce a circular dependency, making it impossible for either object to be destroyed. If it were a normal reference type (foo&), it risks refering to a deleted object when it attempts to use it, as the lifetime of foo is independent of bar.

The solution is to use a std::weak_ptr<foo>, as on line 33. When bar needs to use foo, it checks if bar still exists by calling lock on the std::weak_ptr to take temporary shared ownership (line 26). If the returned std::shared_ptr is not empty, bar can safely use it to access the foo object (lines 27–29).

Contributors

  • Joseph Mansfield
  • dyp-cpp
  • Migrant Coder

Last Updated

10 December 2017

Source

Fork this pattern on GitHub

Share