Shiklo Tools
PDF40
Image20
Calculators & Converters25
Text & Writing13
Developer26
Video14
Audio14
Document14
Data & Spreadsheet12
Web & SEO9
OCR & Scanning5
Archive & File12
Security & Privacy23
Health & Medical29
QR & Barcode5

C++ Smart Pointers

A smart pointer owns an object created on the heap and deletes it automatically at the right moment. With smart pointers, memory leaks and double deletes become very hard to write. They live in the memory header.

unique_ptr: one owner

std::unique_ptr is the only owner of its object. When the unique_ptr goes away, the object is deleted. std::make_unique creates both in one step.

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

struct Book {
    std::string title;
    explicit Book(const std::string& t) : title(t) { std::cout << "+ " << title << "\n"; }
    ~Book() { std::cout << "- " << title << "\n"; }
};

int main() {
    {
        auto a = std::make_unique<Book>("C++ Basics");
        std::cout << "reading " << a->title << "\n";
    }                                   // a goes away: the book is deleted
    std::cout << "after the block\n";
    return 0;
}
Output
+ C++ Basics
reading C++ Basics
- C++ Basics
after the block

A unique_ptr cannot be copied, because then two owners would delete the same object. Ownership can be moved with std::move, which leaves the old pointer empty:

#include <iostream>
#include <memory>
#include <utility>
#include <vector>

int main() {
    auto p = std::make_unique<int>(42);
    auto q = std::move(p);                        // ownership moves to q
    std::cout << (p ? "p set" : "p empty") << ", *q = " << *q << "\n";

    std::vector<std::unique_ptr<int>> box;        // a vector that owns its objects
    box.push_back(std::make_unique<int>(1));
    box.push_back(std::move(q));
    std::cout << box.size() << " items, second " << *box[1] << "\n";
    return 0;
}
Output
p empty, *q = 42
2 items, second 42

shared_ptr: several owners

std::shared_ptr lets several pointers own the same object. It counts the owners (use_count) and deletes the object when the last one goes away.

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

struct Notes {
    std::string text;
    ~Notes() { std::cout << "notes deleted\n"; }
};

int main() {
    auto s1 = std::make_shared<Notes>();
    s1->text = "shared";
    {
        auto s2 = s1;                       // a second owner
        std::cout << "owners: " << s1.use_count() << "\n";
    }
    std::cout << "owners: " << s1.use_count() << "\n";
    return 0;
}
Output
owners: 2
owners: 1
notes deleted

weak_ptr

A std::weak_ptr observes an object owned by shared_ptrs without owning it, so it does not keep the object alive. It is used to break cycles (two objects that own each other would never be deleted) and for caches. Call lock() to get a shared_ptr if the object still exists.

Which one to use

  • Prefer plain values and containers (std::vector<Book>) when you can.
  • Use unique_ptr when an object needs one owner on the heap: polymorphic objects, large objects, things owned by one class. This is the common case.
  • Use shared_ptr only when ownership is really shared and no single owner is obvious.
  • Raw pointers and references are fine for using an object someone else owns; they should not own anything.

Practice exercises

  1. Make a vector of unique_ptr<Shape> (see Polymorphism) and print the total area.
  2. Write a function that takes a unique_ptr<int> by value, call it with std::move, and check that the original is empty.
  3. Create two shared_ptrs to one object and print use_count before and after calling reset() on one of them.