C++ Tutorial · Memory and Pointers · Lesson 11 of 21

C++ Smart Pointers and RAII

unique_ptr, shared_ptr, RAII and why you rarely write new/delete.

RAII

RAII (Resource Acquisition Is Initialisation) is the heart of modern C++: an object acquires a resource in its constructor and releases it in its destructor, which runs automatically when the object goes out of scope — even if an exception is thrown:

Example 1
#include <iostream>
#include <string>

class FileHandle {
public:
    explicit FileHandle(std::string name) : name_(std::move(name)) {
        std::cout << "open " << name_ << '\n';
    }
    ~FileHandle() { std::cout << "close " << name_ << '\n'; }

private:
    std::string name_;
};

int main() {
    std::cout << "start\n";
    {
        FileHandle a("log.txt");
        FileHandle b("data.csv");
        std::cout << "using files\n";
    }   // destructors run here, in reverse order
    std::cout << "end\n";
}

Output

start
open log.txt
open data.csv
using files
close data.csv
close log.txt
end

Run this on your computer — see “Get Started” for setup.

Smart pointers

Never manage heap memory with raw new/delete. Use:

  • std::unique_ptr<T> — single owner; freed automatically. Create with std::make_unique.
  • std::shared_ptr<T> — shared ownership with a reference count. Create with std::make_shared.
Example 2
#include <iostream>
#include <memory>
#include <string>

struct Widget {
    std::string name;
    explicit Widget(std::string n) : name(std::move(n)) {}
    ~Widget() { std::cout << "destroy " << name << '\n'; }
    void draw() const { std::cout << "draw " << name << '\n'; }
};

int main() {
    auto owner = std::make_unique<Widget>("button");
    owner->draw();
    auto moved = std::move(owner);   // ownership transferred; owner is now null
    std::cout << std::boolalpha << (owner == nullptr) << '\n';

    auto shared = std::make_shared<Widget>("logo");
    {
        auto copy = shared;
        std::cout << "owners: " << shared.use_count() << '\n';
    }
    std::cout << "owners: " << shared.use_count() << '\n';
}

Output

draw button
true
owners: 2
owners: 1
destroy logo
destroy button

Run this on your computer — see “Get Started” for setup.

Test yourself

Which smart pointer has exactly one owner?

  1. std::shared_ptr
  2. std::unique_ptr
  3. std::weak_ptr
  4. std::auto_ptr
Show answer

Answer: std::unique_ptr