Modern C++ Programming
Learn the fundamentals and advanced features of Modern C++ to build efficient, maintainable, and high-performance applications.
Illustration of a simple physics simulation
Chapter 4 — Memory, Ownership, and RAII

Memory is the foundation of C++. Ownership is the architecture of C++. RAII is the philosophy of C++.

If you understand these three ideas deeply, you understand modern C++.

This chapter teaches you how modern C++ manages memory safely, predictably, and efficiently — without relying on manual new/delete, without leaking resources, and without creating fragile architectures. These concepts will shape every system you build later in the book.

Why Ownership Matters

In modern C++, ownership determines architecture.

Ownership answers:

When ownership is unclear, systems become fragile. When ownership is explicit, systems become robust.

Modern C++ gives you tools to express ownership clearly.

Raw Pointers Are Not Owners

Raw pointers (T*) do not express ownership.

A raw pointer means:

Raw pointers are non owning references, nothing more.

Use them when:

Example:

void AttachChild(Node* child); // does not own child

This is clear and intentional.

References Are Non Null, Non Owning

References (T&) are:

Use them when:

Example:

void Normalize(Vec3& v); // v must exist

References express strong intent.

Smart Pointers Express Ownership

Modern C++ uses smart pointers to express ownership explicitly:

std::unique_ptr<T> — Exclusive Ownership

Example:

std::unique_ptr<Texture> texture = std::make_unique<Texture>("wood.png");

This is the modern replacement for new.

std::shared_ptr<T> — Shared Ownership

Example:

std::shared_ptr<Model> model = std::make_shared<Model>("tree.obj");

Use shared ownership sparingly — only when truly needed.

std::weak_ptr<T> — Non Owning Reference to Shared Object

Example:

std::weak_ptr<Node> parent;

Weak pointers express “I refer to this, but I do not keep it alive.”

RAII: The Heart of Modern C++

RAII (Resource Acquisition Is Initialization) means:

RAII applies to:

Example:

class File {
public:
    File(const std::string& path)
        : handle(std::fopen(path.c_str(), "rb"))
    {}

    ~File()
    {
        if (handle)
            std::fclose(handle);
    }

private:
    std::FILE* handle;
};

This is modern C++ at its best: safe, simple, predictable.

Never Use new and delete Directly

Modern C++ avoids manual memory management.

Instead of:

Texture* tex = new Texture("wood.png");
delete tex;

Use:

auto tex = std::make_unique<Texture>("wood.png");

Or, if shared:

auto tex = std::make_shared<Texture>("wood.png");

Manual memory management is error prone and unnecessary.

Move Semantics: Efficient Ownership Transfer

Move semantics allow ownership to transfer cheaply.

Example:

std::unique_ptr<Texture> a = std::make_unique<Texture>("wood.png");
std::unique_ptr<Texture> b = std::move(a);

After the move:

Move semantics make modern C++ efficient and expressive.

Copy Semantics: Value Behavior

Copy semantics apply to value types:

Vec3 a{1,2,3};
Vec3 b = a; // cheap copy

Copying is safe and predictable when:

Avoid copying types that manage resources.

Ownership Patterns in Real Systems

Modern C++ uses consistent ownership patterns:

Exclusive ownership for engine resources
std::unique_ptr<Texture> texture;
Shared ownership for scene graphs
std::shared_ptr<Node> root;
Weak references for parent pointers
std::weak_ptr<Node> parent;
Raw pointers for non owning references
Node* currentTarget; // does not own
References for required parameters
void Update(Transform& t);

These patterns make systems predictable and maintainable.

Avoiding Common Ownership Mistakes

Common ownership mistakes to avoid include:

Modern C++ avoids these pitfalls through clear ownership rules.

Summary

In this chapter, you learned:

These principles prepare you for the engineering chapters that follow.