Memory and RAII

Memory and RAII

Object lifetime, stack vs heap, smart pointers, and resource safety patterns.

Memory and RAII

Lifetime categories

Prefer RAII

Resource Acquisition Is Initialization means the object owns the resource and releases it in the destructor.

class FileHandle {
public:
    explicit FileHandle(std::FILE* file) : file_{file} {}
    ~FileHandle() {
        if (file_) std::fclose(file_);
    }

private:
    std::FILE* file_{};
};

Smart pointers

auto p = std::make_unique<int>(42);
auto s = std::make_shared<std::string>("hello");
std::weak_ptr<std::string> weak = s;

Move semantics

std::vector<std::string> names;
std::string temp = "Ada";
names.push_back(std::move(temp));

Move when ownership or expensive state should transfer, not just because std::move exists.

Best-practice reminders

Custom deleters

using FilePtr = std::unique_ptr<std::FILE, int(*)(std::FILE*)>;
FilePtr file(std::fopen("data.txt", "r"), &std::fclose);

Custom deleters let smart pointers manage non-memory resources such as file handles, sockets, or OS descriptors.

Shared ownership warning

struct Node {
    std::shared_ptr<Node> next;
    std::weak_ptr<Node> prev;
};

If both directions used std::shared_ptr, the nodes could keep each other alive forever. Use std::weak_ptr to break cycles.

Views are not owners

Exception-safety checklist

Quick ownership guide

Example in practice

#include <memory>

int main() {
    auto resource = std::make_unique<int>(7);
    return *resource;
}

Try this variation

Transfer ownership out of one scope and into another with `std::move`. It is the fastest way to see what unique ownership really means.

#include <memory>

std::unique_ptr<int> make_value() {
    auto value = std::make_unique<int>(42);
    return value;
}