C/C++ Arena

Step 5 of 5

weak_ptr

shared_ptr has one weakness: cycles. If object A holds a shared_ptr to B and B holds one back to A, each keeps the other's count above zero, so neither is ever deleted. That's a memory leak.

std::weak_ptr solves it. It watches a shared object without owning it: it doesn't add to the count and doesn't keep the object alive. To use the object, call lock(). You get a shared_ptr that's valid while you hold it, or an empty one if the object is already gone.

#include <iostream>
#include <memory>
#include <string>

struct Room {
    std::string name;
};

void check(const std::weak_ptr<Room>& w) {
    if (auto r = w.lock()) {
        std::cout << "still there: " << r->name << " (owners " << r.use_count() << ")\n";
    } else {
        std::cout << "room is gone\n";
    }
}

int main() {
    std::weak_ptr<Room> last_visited;
    {
        auto kitchen = std::make_shared<Room>(Room{"kitchen"});
        last_visited = kitchen;                 // does not add an owner
        std::cout << "owners " << kitchen.use_count() << "\n";
        check(last_visited);
    }                                           // the only owner dies here
    check(last_visited);
    std::cout << "expired: " << last_visited.expired() << "\n";
}
owners 1
still there: kitchen (owners 2)
room is gone
expired: 1

How it works

Where it's used

Your turn: write std::string describe(const std::weak_ptr<std::string>& w) returning "tracking NAME" if the object is alive and "lost" otherwise.

Previous: shared_ptr