advanced20 min

Smart Pointers: unique_ptr and shared_ptr

Applying RAII to heap memory, so you never write a raw delete yourself.

What you'll learn

  • Create heap-allocated objects with std::make_unique instead of raw new
  • Explain that std::unique_ptr automatically deletes its object when it goes out of scope
  • Distinguish unique_ptr's single-owner model from shared_ptr's reference-counted, shared-ownership model

Explanation

std::unique_ptr (from <memory>) is an RAII wrapper around a raw pointer to heap memory: it owns the object it points to, and its destructor calls delete automatically when the unique_ptr itself goes out of scope -- you never write a raw delete for memory owned by a unique_ptr. The idiomatic way to create one is std::make_unique<Widget>(1), which allocates a Widget and wraps it in a unique_ptr<Widget>, rather than writing std::unique_ptr<Widget>(new Widget(1)) yourself.

As its name suggests, unique_ptr models single ownership: exactly one unique_ptr owns a given object at a time. It can't be copied (copying a unique_ptr is a compile error), only moved -- transferring ownership from one unique_ptr to another, after which the original no longer owns anything. This is deliberately restrictive: it makes "who is responsible for deleting this" unambiguous, at compile time, for every object a unique_ptr manages.

std::shared_ptr relaxes that restriction for cases where genuinely shared ownership is needed: multiple shared_ptrs can point to the same object simultaneously, and it uses reference counting internally -- the object is deleted only once the last shared_ptr owning it is destroyed or reset, not before. This is more flexible than unique_ptr but has real runtime overhead (maintaining that count) and complexity (a reference cycle between shared_ptrs can leak memory, since the count never reaches zero) that unique_ptr doesn't have -- the general modern-C++ guidance is to reach for unique_ptr by default, and only use shared_ptr when you genuinely need multiple simultaneous owners.

Guided lab

Predict: A unique_ptr's automatic cleanup

C++Not executed
This lab does not run in your browser or on VisaSparkSchools's servers. Read the code, predict what it does, then reveal the real expected output.

Read this program and predict exactly what it prints, in order.

#include <iostream>
#include <memory>

class Widget {
public:
    Widget(int id) : id_(id) {
        std::cout << "Widget " << id_ << " created" << std::endl;
    }
    ~Widget() {
        std::cout << "Widget " << id_ << " destroyed" << std::endl;
    }
    int id() const { return id_; }
private:
    int id_;
};

int main() {
    std::unique_ptr<Widget> w = std::make_unique<Widget>(1);
    std::cout << "Using widget " << w->id() << std::endl;
    return 0;
}

Stuck? Get a hint.

Common mistakes

  • Writing a raw `new`/`delete` pair for a resource that could instead be owned by a unique_ptr, losing RAII's automatic cleanup guarantee.
  • Trying to copy a unique_ptr directly, forgetting it's move-only -- ownership transfers, it never duplicates.
  • Reaching for shared_ptr by default 'just in case,' instead of using unique_ptr unless multiple simultaneous owners are genuinely needed.

Knowledge check

Knowledge check

1. What happens when a std::unique_ptr goes out of scope?
2. Can a std::unique_ptr be copied?
3. What does std::shared_ptr use to decide when to delete its managed object?

Takeaway

Prefer std::make_unique for heap allocation by default -- its destructor deletes automatically, and single ownership keeps cleanup unambiguous; reach for shared_ptr only when genuinely shared ownership is needed.

Summary

unique_ptr applies RAII to heap memory with single, move-only ownership and automatic deletion; shared_ptr allows shared ownership via reference counting, at the cost of runtime overhead and cycle-leak risk.

References

Your notes

Notes save automatically.

Finished this lesson?

Mark it complete to track your progress and schedule a future review.