← thecodex.expert · The Codex Family of Knowledge

Free · No account · Official sources only

C++ — Cradle to Mastery

A complete, structured path through C++ — from Bjarne Stroustrup's 1979 'C with Classes' to RAII, move semantics, and the concepts/coroutines/ranges trio that reshaped the language after C++20. Every lesson points at reference pages already written and verified on this site. Free, no account, no sign-up.

29 lessons 6 stages ~22 hours of reading 10 projects C++23 (ISO/IEC 14882:2024) · curriculum current as of 2026
Start Lesson 1 → Browse the reference instead

How this course works

1
Follow the stages in orderEach stage assumes the one before it. Stage 3 in particular assumes Stage 2 cold.
2
Read the tab the lesson namesReference pages have Beginner, Intermediate and Expert tabs. Read only what the lesson asks for on a first pass.
3
Run every exampleKeep the playground open in a second tab. Reading code you have not run is how misunderstandings survive.
4
Build after each stageDo not save all ten projects for the end. Pick one up as soon as a stage gives you enough to attempt it.
Casual pace: ~10 weeks at 4 hours a week
Steady pace: ~5 weeks at 8 hours a week
Intensive: ~2 weeks full-time
STAGE 0

Before You Start

Bjarne Stroustrup's 1979 bet — C's performance with real object-oriented abstraction — still defines the language today. These two lessons explain why, and get a compiler installed.

LESSON 1

What is C++?

Bjarne Stroustrup started with 'C with Classes' in 1979

Stroustrup's original goal was C's raw performance combined with real object-oriented abstraction — a bet that classes and zero-cost abstraction could coexist with C's closeness to the machine. That same tension between abstraction and control still shapes every design decision C++ makes today.

📚 🟩 Read the Beginner tab only.
Key focus: Why C++ started as 'C with Classes,' and how that founding tension still shapes the language.
⏱ 30 min
Required Reading
→
What is C++? — The Codex

C++'s origin as an extension of C, the object-oriented abstraction Stroustrup added, and where C++23 sits in that history.

LESSON 2

Setup and Compiler

GCC, Clang, and MSVC — three genuinely different compilers

Unlike languages with one reference implementation, C++ has three real, independently maintained compilers in everyday use — GCC, Clang, and MSVC — each adopting new standard features at its own pace. Getting one installed and a first file compiled is this lesson's entire goal.

📚 🟩 Read the Beginner tab only.
Key focus: Installing a compiler, and knowing that GCC/Clang/MSVC genuinely differ in which standard features they support.
⏱ 30 min
Required Reading
→
Setup and Compiler — The Codex

Installing GCC/Clang/MSVC, compiling and running a first program, and basic compiler flags for standard version.

STAGE 1

Language Fundamentals

C++ is fully statically typed like C, but with real additions on top: type inference, overloading, references instead of raw pointers, and namespaces to keep large codebases sane. Five lessons before classes properly begin.

LESSON 3

Variables and Types

auto infers a type at compile time — C++ stays fully statically typed

The <code>auto</code> keyword saves you from writing out a long type by hand, but it changes nothing about C++'s static typing: the compiler still determines and locks in a concrete type at compile time, it just infers it from the initializer instead of requiring you to spell it out.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Why auto is inference, not dynamic typing, and where it helps versus obscures.
⏱ 30 min
Required Reading
→
Variables and Types — The Codex

Fundamental types, auto's type-inference rules, const, and the static typing C++ keeps even with auto.

LESSON 4

Control Flow

The range-based for loop eliminated most manual index bookkeeping

C++11's range-based <code>for</code> loop lets you iterate a container's elements directly, without hand-managing an index or an iterator — eliminating an entire category of off-by-one bugs that plagued C-style loops for decades.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: How the range-based for loop removes manual index bookkeeping, and when the classic form is still needed.
⏱ 30 min
Required Reading
→
Control Flow — The Codex

if/else, while/do-while, the classic indexed for loop, and the range-based for loop introduced in C++11.

LESSON 5

Functions

Overloading and default arguments — real C++ additions C never had

Function overloading (multiple functions sharing a name, distinguished by parameter types) and default arguments are both genuine C++ additions with no C equivalent — C requires a separately named function for each variant instead. Both features rely on the compiler resolving the right call at compile time.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: How overload resolution picks a function at compile time, and how default arguments interact with it.
⏱ 45 min
Required Reading
→
Functions — The Codex

Function declarations, overloading and its resolution rules, default arguments, and inline functions.

LESSON 6

References

An alias for an existing variable — not a pointer, can't be null

A C++ reference is not a pointer wearing a different syntax: it is a genuine alias for an existing variable, it cannot be reseated to refer to something else after initialization, and by the language's own rules it cannot be null. These constraints are exactly what makes references safer to pass around than raw pointers.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Why a reference's can't-be-null, can't-be-reseated guarantees make it a safer default than a pointer.
⏱ 30 min
Required Reading
→
References — The Codex

Reference declaration and initialization, reference parameters, const references, and how references differ from pointers.

LESSON 7

Namespaces

Two libraries can each define Vector with zero conflict

Namespaces let two entirely unrelated libraries each define a class named <code>Vector</code> without any collision, as long as each lives inside its own namespace — the mechanism that makes large C++ codebases and third-party libraries safely composable.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: How namespaces prevent naming collisions at scale, and the tradeoffs of using-declarations vs. using-directives.
⏱ 30 min
Required Reading
→
Namespaces — The Codex

Namespace declarations, nested namespaces, using-declarations vs. using-directives, and the std namespace.

STAGE 2

Classes, RAII and Memory — C++'s Defining Discipline

This is the stage that makes C++, C++: real object-oriented classes wired to automatic resource management, the memory model underneath it, and the move semantics that make it fast — then the last lesson ties every piece together into one realistic class. Seven lessons, the heart of the course.

LESSON 8

Inheritance and Polymorphism

Methods are NOT virtual by default — forgetting the keyword silently breaks it

Unlike Java, a C++ method must be explicitly marked <code>virtual</code> to participate in dynamic dispatch — forget the keyword and a call through a base-class pointer silently resolves to the base class's version instead of the derived override, with no compiler error at all.

📚 ⚡ Intermediate.
Key focus: Why virtual must be explicit in C++, and what silently breaks when it's forgotten.
⏱ 1 hours
Required Reading
→
Inheritance and Polymorphism — The Codex

Base and derived classes, the virtual keyword and dynamic dispatch, pure virtual functions, abstract classes, and override.

LESSON 9

Operator Overloading

a + b can call your own code — exactly how std::string and std::vector work

Operator overloading lets a custom type respond to <code>+</code>, <code>==</code>, <code>&lt;&lt;</code> and the rest with your own code, resolved at compile time by argument types — the exact same mechanism the standard library itself uses to make <code>std::string</code> concatenation and stream output work.

📚 ⚡ Intermediate.
Key focus: Which operators are safe to overload, and how the standard library relies on this exact mechanism itself.
⏱ 45 min
Required Reading
→
Operator Overloading — The Codex

Overloading arithmetic, comparison, and stream operators, member vs. free-function overloads, and common conventions.

LESSON 10

Multiple Inheritance

A class can genuinely extend two classes — and the diamond problem follows

C++ genuinely allows a class to inherit from two (or more) base classes at once, unlike languages that restrict inheritance to a single parent. The famous diamond problem — two paths to a shared ancestor producing ambiguous, duplicated state — is the real complication that follows, and virtual inheritance is C++'s specific answer to it.

📚 ⚡ Intermediate.
Key focus: The diamond problem as a real, concrete consequence of multiple inheritance, and how virtual inheritance resolves it.
⏱ 45 min
Required Reading
→
Multiple Inheritance — The Codex

Multiple base classes, the diamond problem, virtual inheritance, and when multiple inheritance is (and isn't) the right tool.

LESSON 11

Memory Management

new and delete replace malloc/free — modern style barely uses either directly

<code>new</code> and <code>delete</code> replace C's <code>malloc</code>/<code>free</code> and also run constructors and destructors, but idiomatic modern C++ style says to barely ever call either one directly — that responsibility belongs to RAII types and smart pointers instead, which the next two lessons cover.

📚 ⚡ Intermediate.
Key focus: Why new/delete exist but modern style avoids calling them directly, deferring to RAII instead.
⏱ 45 min
Required Reading
→
Memory Management — The Codex

new/delete vs. malloc/free, constructor/destructor invocation, memory leaks, and why direct new/delete is now considered a smell.

LESSON 12

Smart Pointers

unique_ptr and shared_ptr wrap new/delete in RAII

<code>std::unique_ptr</code> and <code>std::shared_ptr</code> wrap raw <code>new</code>/<code>delete</code> calls inside RAII, automatically freeing memory when the smart pointer itself goes out of scope. Modern C++ style barely calls <code>new</code> or <code>delete</code> directly anymore because of exactly these two types.

📚 ⚡ Intermediate.
Key focus: Choosing unique_ptr's exclusive ownership versus shared_ptr's reference-counted ownership.
⏱ 45 min
Required Reading
→
Smart Pointers — The Codex

unique_ptr and its move-only ownership, shared_ptr and reference counting, weak_ptr for breaking cycles, and make_unique/make_shared.

LESSON 13

Move Semantics

Instead of copying a huge vector, C++11 lets you steal its buffer

Move semantics, introduced in C++11, let you transfer — 'steal' — a large object's internal buffer instead of copying it, leaving the original in a valid-but-empty state while the operation itself costs nearly nothing. This is the single biggest performance idea C++11 added to the language.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: The steal-not-copy idea behind move semantics, and how rvalue references make it possible.
⏱ 1 hours
Required Reading
→
Move Semantics — The Codex

Rvalue references (&&), std::move, move constructors and move assignment, and how they interact with the rule of five.

LESSON 14

Classes and RAII, Tied Together

Constructors, destructors, smart pointers, the rule of five, and move semantics together

This lesson is the synthesis for the stage: class definition, constructors and destructors, RAII as the unifying idea, smart pointers, the rule of five, and move semantics &mdash; combined into the actual discipline experienced C++ code follows for resource management. Read it once each piece is familiar on its own.

📚 ⚡ Intermediate.
Key focus: Seeing RAII, smart pointers, the rule of five, and move semantics work together as one coherent discipline.
⏱ 1.25 hours
Required Reading
→
Classes and RAII, Tied Together — The Codex

Class definitions, constructors/destructors, RAII, smart pointers, the rule of five (and rule of zero), and move semantics together.

STAGE 3

Templates and the STL

Generic code and the Standard Template Library — how C++ gets type-safe reusability, the containers you'll reach for constantly, and the concepts/lambdas that make templates usable in practice. Five lessons.

LESSON 15

The STL Containers

vector should be your default — reach for anything else with a specific reason

<code>std::vector</code> is the correct default container for nearly every job in C++, with contiguous storage and cache-friendly access; reaching for <code>list</code>, <code>map</code>, or anything else should be a deliberate choice justified by a specific access pattern, not a habit.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Why vector is the right default, and the specific situations that justify a different container.
⏱ 1 hours
Required Reading
→
The STL Containers — The Codex

vector, array, deque, list, map/unordered_map, set/unordered_set, and choosing between them by access pattern.

LESSON 16

Lambda Expressions

You must explicitly choose how each outer variable is captured

Unlike Python or JavaScript closures, a C++ lambda forces you to explicitly state how it captures each outer-scope variable — by copy or by reference — rather than capturing everything implicitly. This explicitness is exactly what prevents a whole category of dangling-reference bugs in captured lambdas.

📚 ⚡ Intermediate.
Key focus: Why explicit capture (by copy or reference) is required, and the dangling-reference bug it prevents.
⏱ 45 min
Required Reading
→
Lambda Expressions — The Codex

Lambda syntax, capture lists ([=], [&], and named captures), mutable lambdas, and lambdas as function arguments.

LESSON 17

Concepts and Constraints

Before C++20, a bad template argument produced unreadable errors

A template argument that didn't satisfy what a template actually required used to produce hundreds of lines of near-unreadable compiler error, often pointing deep inside library internals rather than at the actual mistake. C++20 concepts finally let a template state its real requirements directly, turning that wall of text into a clear, specific error message.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: How concepts turn an unreadable template error into a clear, specific one.
⏱ 45 min
Required Reading
→
Concepts and Constraints — The Codex

Defining and using concepts, requires clauses, standard concepts (std::integral, std::copyable), and how they improve error messages.

LESSON 18

The STL Algorithms

std::sort, std::find, std::transform replace hand-written loops

The <code>&lt;algorithm&gt;</code> header's functions — <code>std::sort</code>, <code>std::find</code>, <code>std::transform</code> and dozens more — replace hand-written loops with calls that are tested, typically better-optimized than a hand-rolled version, and self-documenting about intent.

📚 ⚡ Intermediate.
Key focus: Reaching for a named algorithm instead of a hand-written loop, and what that buys you.
⏱ 45 min
Required Reading
→
The STL Algorithms — The Codex

std::sort, std::find, std::transform, std::accumulate, and iterators as the glue between containers and algorithms.

LESSON 19

Templates and the STL, Tied Together

Function and class templates, specialisation, containers, iterators and algorithms together

This lesson is the synthesis for the stage: function and class templates, template specialisation, how the STL containers from earlier in this stage are themselves built from templates, iterators as the uniform interface between containers and algorithms, and the algorithms themselves &mdash; the whole generic-programming picture in one place.

📚 ⚡ Intermediate.
Key focus: Seeing how templates, containers, iterators and algorithms form one coherent generic-programming system.
⏱ 1.25 hours
Required Reading
→
Templates and the STL, Tied Together — The Codex

Function templates, class templates, template specialisation, STL containers recap, iterators, and STL algorithms together.

STAGE 4

Errors, Concurrency and Modern Types

What happens when things go wrong, what runs at the same time as what, and the newer standard types built to replace older, riskier patterns. Five lessons.

LESSON 20

Exceptions

Stack unwinding calls every local object's destructor automatically

When a C++ exception propagates, stack unwinding automatically calls the destructor of every local object that goes out of scope along the way — which is exactly why RAII and exceptions work so well together: cleanup happens whether a function returns normally or throws.

📚 ⚡ Intermediate.
Key focus: Why RAII and exceptions are designed to work together through automatic stack unwinding.
⏱ 45 min
Required Reading
→
Exceptions — The Codex

try/catch/throw, exception hierarchies, stack unwinding and destructor calls, and exception safety guarantees.

LESSON 21

The Standard Library

std::optional, std::variant, std::expected replace raw pointers and unions

<code>std::optional</code>, <code>std::variant</code>, and C++23's <code>std::expected</code> each replace a pattern that used to require raw pointers, unions, or exceptions for the exact same job — representing absence, one-of-several-types, or an expected failure, respectively, with real type safety.

📚 ⚡ Intermediate.
Key focus: Which modern standard type replaces which older, less safe pattern, and when to reach for each.
⏱ 45 min
Required Reading
→
The Standard Library — The Codex

std::optional for absence, std::variant for tagged unions, std::expected for fallible operations, and std::string_view.

LESSON 22

Undefined Behaviour

C++ inherits C's UB, then adds its own C++-specific traps

C++ inherits every one of C's undefined-behaviour categories wholesale, then adds genuinely new ones on top — an invalidated iterator used after a container reallocates, or a virtual function called from inside a constructor before the derived class even exists, are two real, C++-specific traps worth knowing by name.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: Two C++-specific UB traps beyond C's own: invalidated iterators and virtual calls from a constructor.
⏱ 45 min
Required Reading
→
Undefined Behaviour — The Codex

UB inherited from C, iterator invalidation, calling virtual functions during construction/destruction, and sanitizer tools.

LESSON 23

Coroutines

co_await/co_yield shipped with almost no ready-to-use types

C++20 added the <code>co_await</code> and <code>co_yield</code> keywords for suspending and resuming a function's execution, but shipped the language feature almost entirely without the concrete coroutine types needed to actually use it — those largely arrived later from third-party libraries, a genuinely unusual way for a major language feature to ship.

📚 🔥 Expert.
Key focus: Why C++20's coroutine keywords needed outside libraries before they were practically usable.
⏱ 45 min
Required Reading
→
Coroutines — The Codex

co_await, co_yield, co_return, the promise-type machinery underneath them, and why library support lagged the language feature.

LESSON 24

Concurrency

Destroying a running std::thread without join() terminates the whole program

Destroying a <code>std::thread</code> object while its thread is still running, without first calling <code>join()</code> or <code>detach()</code>, calls <code>std::terminate</code> and kills the entire program — a sharp-edged default that <code>std::jthread</code>, added in C++20, finally fixes by joining automatically in its own destructor.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: The std::thread footgun std::jthread was specifically added to fix, and why the old behavior was so harsh.
⏱ 45 min
Required Reading
→
Concurrency — The Codex

std::thread and the join-or-terminate rule, mutexes and locks, std::atomic, and std::jthread's automatic join.

STAGE 5

Tooling, Standards and Modern C++

What surrounds the code: the preprocessor C++ inherited, the build systems and test frameworks that hold a real project together, the standards history, and a final lesson tying the whole modern-C++ toolkit together. Five lessons to close out the course.

LESSON 25

The Preprocessor

Templates and constexpr replace most of what macros used to be needed for

C++ inherited C's text-substitution preprocessor wholesale, but templates and <code>constexpr</code> now cover most of the jobs macros used to be the only tool for — type-safe generic code and compile-time computation, without a macro's total lack of type checking or scoping.

📚 ⚡ Intermediate.
Key focus: Which historical macro use cases templates and constexpr have genuinely replaced.
⏱ 30 min
Required Reading
→
The Preprocessor — The Codex

#define and #include recap, conditional compilation, and why templates/constexpr are preferred over macros where they overlap.

LESSON 26

Build Systems

CMake generates build files — it doesn't compile anything itself

CMake is not a compiler or even a build tool in the direct sense: it generates the actual build files — a Makefile, a Ninja file, a Visual Studio project — for whatever tool your platform and toolchain actually prefer, which is exactly why the same CMakeLists.txt works across GCC, Clang, and MSVC alike.

📚 ⚡ Intermediate.
Key focus: Why CMake is a build-file generator rather than a build tool itself, and why that's what makes it portable.
⏱ 45 min
Required Reading
→
Build Systems — The Codex

CMakeLists.txt basics, targets and dependencies, generating and invoking the underlying build tool, and package management options.

LESSON 27

Testing

No built-in test runner — Google Test and Catch2 are what people actually use

C++ ships no standard test runner at all, unlike languages with one built into the toolchain. Google Test and Catch2 are the two frameworks nearly every real C++ codebase reaches for instead, each with genuinely different assertion styles and setup conventions worth knowing both of.

📚 ⚡ Intermediate.
Key focus: Writing and organizing real test suites with Google Test or Catch2, since neither ships with the language.
⏱ 45 min
Required Reading
→
Testing — The Codex

Google Test's TEST macros and fixtures, Catch2's alternative assertion style, and organizing a real C++ test suite.

LESSON 28

C++ Standards History

C++11 was such an overhaul it's called a second birth for the language

C++11 added so much at once — auto, lambdas, move semantics, the range-based for loop, smart pointers — that it is routinely called a second birth for the language, with C++14/17/20/23 each building incrementally on that one foundational release rather than any single one matching its scope.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Why C++11 specifically is treated as the language's real dividing line, and what each later standard added.
⏱ 30 min
Required Reading
→
C++ Standards History — The Codex

Pre-C++11 C++, the C++11 overhaul, and the incremental additions in C++14, C++17, C++20, and C++23.

LESSON 29

Modern C++, Tied Together

auto, lambdas, move semantics, constexpr, concepts, ranges and coroutines together

This lesson is the course's synthesis and capstone: <code>auto</code>, lambdas, move semantics, <code>constexpr</code>, structured bindings, <code>std::optional</code>, concepts, ranges, and coroutines &mdash; the individual modern-C++ features from across this entire course, seen together as the toolkit that actually defines what 'writing modern C++' means in 2026.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: Seeing every modern-C++ feature from this course work together as one coherent, current style.
⏱ 1.25 hours
Required Reading
→
Modern C++, Tied Together — The Codex

auto, lambdas, move semantics, constexpr, structured bindings, std::optional, concepts, ranges, and coroutines, together.

STAGE 6

Concepts That Cross Languages

These pages explain ideas that are not specific to C++ — they apply to every language you will ever learn. Read them once and the next language costs you far less effort. They pair well with the lessons above rather than replacing them.

STAGE 7

Build Real Things — 10 Projects

Reading is not enough. These 10 projects — five basic, five medium — are chosen because each one exercises something specific you learned above, and because they are genuinely idiomatic C++ rather than generic exercises. Each link below opens the project brief; the C++ implementation walkthrough is in progress.

BASIC — 5 PROJECTS
→
Number Guessing Game

std::cin input parsing, a guess loop, and <random> for the secret number.

→
Temperature Converter

A small switch or if-chain for conversion direction, and iostream formatting.

→
Word Counter

Reading a file with std::ifstream, and an unordered_map<std::string,int> for a frequency table.

→
To-Do List (CLI)

A struct for the task shape, a std::vector to hold them, and hand-rolled file persistence.

→
Password Generator

Flag-based character-set selection, and <random>'s engines versus the security pitfalls of rand().

MEDIUM — 5 PROJECTS
→
Web Scraper

A raw socket and hand-written HTTP request, since the standard library ships no HTTP client at all.

→
REST API

A minimal HTTP server over raw sockets, with std::variant-based typed responses and manual JSON formatting.

→
CLI Task Manager

A std::variant for subcommands, and std::visit for exhaustive-by-convention dispatch.

→
URL Shortener

An unordered_map-backed store with a std::mutex for thread safety, and std::jthread for the server loop.

→
Log Analyser

Line-by-line parsing with std::istringstream, and STL algorithms for top-N aggregation.

STAGE 8

Practice & Experimentation

Ongoing, not a final step. Use these throughout the course — try every snippet you read, and run anything you are unsure about rather than assuming.

Resources
→
C++ Playground

Run C++ code without installing anything, via the official C++ Playground.

→
C++ Snippets

Copy-ready idiomatic patterns to keep beside you while you build.

→
C++ Reference Hub

All 29 topic pages in one index, for looking things up later.