Smart Pointers: Weak Pointers using lock() Method

What is it?

A Weak Pointer is a part of C++ Smart Pointers that holds a non-owning reference to an object managed by a std::shared_ptr. It is used to track an object, but it allows the object to be deleted when it's no longer used.

The lock() method is used to create a shared_ptr that shares ownership of the managed object (if it exists). If the managed object has been deleted (which means, it does not exist), then it would return an empty shared_ptr.


Syntax

The syntax for using std::weak_ptr::lock() method is:

std::shared_ptr<T> lock() const noexcept;

Where,

  • T is the type of the object that is being pointed by std::weak_ptr.



How to use it

To use the lock() method, follow the below steps:

  1. Create a std::shared_ptr and initialize it with an object.
  2. Create a std::weak_ptr from the shared_ptr.
  3. Use the lock() method to get a std::shared_ptr to the object if it exists.



Program code snippet example

#include <iostream>
#include <memory>

using namespace std;

int main() {

    // Creating a shared_ptr and initializing it with an integer.
    shared_ptr<int> myShared = make_shared<int>(10);

    // Creating a weak_ptr from the shared_ptr.
    weak_ptr<int> myWeak = myShared;

    {
        // Locking the weak_ptr to get a shared_ptr to the object.
        shared_ptr<int> myLocked = myWeak.lock();

        // If the object still exists, print it.
        if(myLocked) {
            cout << "Object exists: " << *myLocked << endl;
        } else {
            cout << "Object has been deleted!" << endl;
        }
    }

    // Deleting the object managed by the shared_ptr.
    myShared.reset();

    {
        // Trying to lock the weak_ptr again.
        shared_ptr<int> myLocked = myWeak.lock();

        // If the object still exists, print it.
        if(myLocked) {
            cout << "Object exists: " << *myLocked << endl;
        } else {
            cout << "Object has been deleted!" << endl;
        }
    }

    return 0;
}

Output:

Object exists: 10
Object has been deleted!



Important to know

  • std::weak_ptr does not extend the lifetime of the managed object. The object could be deleted while it's being pointed to by a std::weak_ptr.
  • std::weak_ptr::lock() method is used to check whether the object exists before accessing it.
  • std::weak_ptr is designed to help eliminate the problem of dangling pointers and cyclic references that can lead to memory leaks.



Best practices

When using std::weak_ptr::lock(), it is important to keep the following best practices in mind:

  1. Use std::weak_ptr to prevent cyclic references: If you have objects that reference each other in a cyclic way (for example, in a parent-child relationship where the parent has a std::shared_ptr to the child, and the child has a std::shared_ptr to the parent), use a std::weak_ptr for one of the pointers to break the cycle.

  2. Always check the existence of the object before accessing it: Before accessing the object pointed to by a std::weak_ptr, always check

whether it exists by calling the lock() method and checking the returned std::shared_ptr.

  1. Avoid using std::weak_ptr if not necessary: The use of std::weak_ptr adds complexity to the code. If you don't have cyclic references or dangling pointers problem, prefer using std::shared_ptr.




Call the lock() member function from the weak pointer, boss_ptr2. Then call the attack() method of the shared pointer object of Boss class.