std::shared_ptr
Sometimes an object genuinely has several owners and no single one of them knows who will finish last — think of a shared cache entry used by three independent subsystems, where the entry should live exactly as long as someone still needs it. std::shared_ptr handles this by counting how many owners there are and deleting the object only when the last one goes away. Where unique_ptr says 'exactly one owner', shared_ptr says 'as many as you like, and the object dies with the last of them'.
It works through a small heap-allocated control block that sits alongside (or next to) the object. The control block holds a strong reference count: copying a shared_ptr increments it, destroying or resetting one decrements it, and when it hits zero the managed object is destroyed and then the control block is freed. Each shared_ptr is therefore two pointers wide — one to the object, one to the control block — and the count updates are atomic so multiple threads can safely copy and destroy shared_ptrs to the same object. You should create them with std::make_shared<T>(args...), which allocates the object and its control block together in one allocation, saving a heap trip and improving locality.
Why it matters: shared_ptr is the tool for true shared ownership and for lifetime that outlives any single scope. But it is not free, and that is the honest part: the atomic reference-count operations cost more than a raw pointer, the control block is extra memory, and — critically — two shared_ptrs that point at each other form a reference cycle whose counts never reach zero, so the objects leak. Breaking such cycles is exactly the job of std::weak_ptr. Reach for unique_ptr first; use shared_ptr only when ownership is genuinely shared, not merely as a lazy default.
auto a = std::make_shared<Node>(); auto b = a; // count is now 2; the Node is deleted only when both a and b are gone
Each copy bumps the strong count; the object's destructor runs when the count drops to zero.
Common misconception: shared_ptr is not a drop-in 'safe pointer' — its reference counting is thread-safe for the count, but the pointed-to object is not automatically protected from data races, and two shared_ptrs pointing at each other leak forever. Use it for shared ownership, not as a default.