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.
In modern C++,
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 (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 (T&) are:
Use them when:
Example:
void Normalize(Vec3& v); // v must exist
References express strong intent.
Modern C++ uses smart pointers to express ownership explicitly:
std::unique_ptr<T> —
Example:
std::unique_ptr<Texture> texture = std::make_unique<Texture>("wood.png");
This is the modern replacement for new.
std::shared_ptr<T> —
Example:
std::shared_ptr<Model> model = std::make_shared<Model>("tree.obj");
Use shared ownership sparingly — only when truly needed.
std::weak_ptr<T> —
Example:
std::weak_ptr<Node> parent;
Weak pointers express “I refer to this, but I do not keep it alive.”
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.
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 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 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.
Modern C++ uses consistent ownership patterns:
std::unique_ptr<Texture> texture;
std::shared_ptr<Node> root;
std::weak_ptr<Node> parent;
Node* currentTarget; // does not own
void Update(Transform& t);
These patterns make systems predictable and maintainable.
Common ownership mistakes to avoid include:
Modern C++ avoids these pitfalls through clear ownership rules.
In this chapter, you learned:
These principles prepare you for the engineering chapters that follow.