std::weak_ptr

Spirit: Borrowed Reference That Could Be Invalid

  • Tied to a shared pointer

  • Lightweight reference: shared pointer might become invalid (because all references are dropped)

  • ⟶ ask before use!

Methods

Method

Description

std::weak_ptr()

Not tied to any shared pointer

std::weak_ptr(const std::weak_ptr&)

Copy constructor

std::weak_ptr(std::weak_ptr&& from)

Move constructor; from is not tied to any shared pointer afterwards (see Move Semantics, Rvalue References, Perfect Forwarding)

std::weak_ptr(const std::shared_ptr& that)

Tie constructed object to that

reset()

Untie

lock()

Creates a std::shared_ptr that references the managed object

Basic Usage

#include "sensors.h"

#include <gtest/gtest.h>
#include <memory>


TEST(weak_ptr_suite, basic)
{
    // original object, referenced via shared_ptr
    std::shared_ptr<Sensor> sensor{new RandomSensor{20, 40}};

    // borrowed reference: weak_ptr
    std::weak_ptr<Sensor> borrowed_sensor{sensor};

    // refcount still one
    ASSERT_EQ(sensor.use_count(), 1);

    auto another_reference = borrowed_sensor.lock();

    ASSERT_EQ(another_reference.get(), sensor.get());
    ASSERT_EQ(sensor.use_count(), 2);
}

A Real-Life Example

#include "sensors.h"

#include <map>
#include <memory>
#include <thread>
#include <chrono>
#include <iostream>


int main()
{
    std::map<std::string, std::shared_ptr<Sensor>> sensors;
    sensors["rand1"] = std::make_shared<RandomSensor>(20, 40);
    sensors["rand2"] = std::make_shared<RandomSensor>(10, 30);
    sensors["const"] = std::make_shared<ConstantSensor>(36.5);

    std::weak_ptr<Sensor> sensor_ref{sensors["rand1"]};

    std::thread measurement_thread([sensor_ref]() {
        while (true) {
            if (auto sensor = sensor_ref.lock()) {
                std::cout << sensor->get_temperature() << std::endl;
                std::this_thread::sleep_for(std::chrono::milliseconds(700));
            }
            else {
                std::cout << "terminating" << std::endl;
                break;
            }
        }
    });

    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "removing sensor" << std::endl;
    sensors.erase("rand1");

    measurement_thread.join();

    return 0;
}