The C++ Textbook

Quick reference

Every chapter's objectives in one place. Use it to find where you are: scan for the first row you cannot honestly claim, and start there.

Foundations

ChapterYou should be able toStandard
Hello, machine
  • Explain what the preprocessor, compiler, assembler, and linker each do
  • Read a compiler error and locate the line it refers to
  • Compile and run a program from source
c++20
Values, types, and names
  • Choose an appropriate built-in type for a quantity
  • Predict the result of integer versus floating-point division
  • Explain what auto deduces and when to avoid it
c++20
Making decisions
  • Write conditions that short-circuit correctly
  • Use switch without falling through by accident
  • Explain why comparing floating-point numbers with == is a trap
c++20
Repetition
  • Write a range-based for loop over a container
  • Convert an index loop to a range loop and back
  • Identify the exit condition that makes a loop terminate
c++20
Functions
  • Choose between passing by value, by reference, and by const reference
  • Explain what overload resolution picks and why
  • Write a function with a default argument without creating ambiguity
c++20
Your toolchain
  • Compile with a warning set that catches real bugs
  • Run a program under AddressSanitizer and read its report
  • Step through a program in a debugger and inspect a variable
c++20

Memory and objects

ChapterYou should be able toStandard
Objects and storage
  • Explain the difference between an object, a value, and a name
  • Predict sizeof for a struct given its members
  • Describe what padding is and why the compiler inserts it
c++20
Pointers
  • Read and write pointer declarations without hesitating
  • Explain what dereferencing a null or dangling pointer does
  • Use pointer arithmetic correctly within an array
c++20
References
  • Choose between a reference and a pointer for a given interface
  • Explain why a reference cannot be reseated
  • Identify when a reference outlives what it refers to
c++20
Lifetime and scope
  • State the lifetime of automatic, static, and dynamic objects
  • Spot a returned reference to a local
  • Explain why destruction order is the reverse of construction
c++20
The stack and the heap
  • Explain why stack allocation is nearly free and heap allocation is not
  • Use new and delete correctly, then explain why you should not
  • Predict when a stack overflow occurs
c++20
Arrays, and why they decay
  • Explain array-to-pointer decay and when it happens
  • Choose std::array or std::vector over a raw array
  • Pass an array to a function without losing its length
c++20
const and constness
  • Read a const declaration right-to-left without guessing
  • Explain the difference between a const pointer and a pointer to const
  • Decide where const belongs in an interface
c++20

Types you make

ChapterYou should be able toStandard
Structs and classes
  • Define a class with a clear public interface
  • Explain the only difference between struct and class
  • Choose what belongs in the interface and what does not
c++20
RAII
  • Explain RAII in terms of construction and destruction
  • Write a class that owns a resource and releases it exactly once
  • Identify a resource leak that RAII would have prevented
c++20
Copying
  • Distinguish a shallow copy from a deep copy
  • Write a correct copy constructor and copy assignment operator
  • Explain the self-assignment problem
c++20
Moving
  • Explain what std::move does and does not do
  • Write a move constructor that leaves the source valid
  • Predict when the compiler moves instead of copies
c++20
Rule of zero, three, five
  • Apply the rule of zero to a class that owns nothing
  • List the five special member functions and when each is generated
  • Explain why declaring a destructor suppresses move operations
c++20
Operator overloading
  • Overload arithmetic and comparison operators idiomatically
  • Use the spaceship operator to generate comparisons
  • Explain when an operator should be a member and when a free function
c++20
Inheritance and virtual functions
  • Explain what a vtable is and what a virtual call costs
  • Write a base class that is safe to delete through
  • Explain why a non-virtual destructor in a base class is a bug
c++20
When not to use inheritance
  • Recognise an is-a relationship that is really has-a
  • Replace an inheritance hierarchy with composition
  • Explain the Liskov substitution principle in concrete terms
c++20

The standard library

ChapterYou should be able toStandard
std::string and text
  • Use std::string and std::string_view appropriately
  • Explain why a string_view can dangle
  • Describe what a char actually holds in a UTF-8 world
c++20
Sequence containers
  • Predict the complexity of insertion for each sequence container
  • Explain vector's growth strategy and reallocation
  • Identify when an iterator is invalidated
c++20
Associative containers
  • Choose between ordered and unordered containers
  • Explain what a hash collision costs
  • Use a custom comparator or hash correctly
c++20
Iterators
  • Name the iterator categories and what each supports
  • Write a function that takes a pair of iterators
  • Explain why end() points past the last element
c++20
Algorithms
  • Replace a hand-written loop with a standard algorithm
  • Use the erase-remove idiom correctly
  • Explain what a projection is in a ranges algorithm
c++20
Ranges and views
  • Compose a pipeline of views
  • Explain what makes a view lazy and cheap to copy
  • Identify when a view dangles
c++20
Smart pointers
  • Choose between unique_ptr, shared_ptr, and a raw pointer
  • Explain the cost of a shared_ptr's control block
  • Break a reference cycle with weak_ptr
c++20
optional, variant, expected
  • Return an optional instead of a sentinel value
  • Use variant with a visitor
  • Explain when expected is better than an exception
c++20
Input, output, formatting
  • Format values with std::format
  • Read input robustly and detect failure
  • Explain why iostreams are slow and when it matters
c++20

Generic programming

ChapterYou should be able toStandard
Function templates
  • Write a function template and explain how it is instantiated
  • Describe what template argument deduction does
  • Explain why template code usually lives in headers
c++20
Class templates
  • Write a class template with a type parameter
  • Use a deduction guide
  • Explain what a partial specialization does
c++20
Deduction and forwarding
  • Explain the difference between auto and template deduction
  • Write a perfectly forwarding wrapper
  • Explain what a forwarding reference is and how to spot one
c++20
Concepts and constraints
  • Write a concept that constrains a template parameter
  • Compare a concept error with an unconstrained template error
  • Use requires clauses to pick between overloads
c++20
Compile-time computation
  • Write a constexpr function and prove it runs at compile time
  • Explain the difference between constexpr, consteval, and constinit
  • Use static_assert to check an invariant at compile time
c++20
Variadic templates
  • Write a variadic function template with a fold expression
  • Explain how a parameter pack is expanded
  • Implement a simple type-safe printf
c++20
Type traits
  • Use standard type traits to constrain or branch code
  • Write a trait with a partial specialization
  • Explain if constexpr and why it beats tag dispatch
c++20
Static polymorphism
  • Implement CRTP and explain what it replaces
  • Compare the cost of virtual dispatch with a template
  • Decide when runtime polymorphism is the right answer anyway
c++20

Correctness

ChapterYou should be able toStandard
Exceptions
  • Throw and catch by the right types
  • Explain what the strong exception guarantee requires
  • Write a function that is exception-safe by construction
c++20
Error handling without exceptions
  • Design an API around expected or an error code
  • Explain the trade-offs against exceptions
  • Handle errors without silently discarding them
c++20
Undefined behaviour
  • List the common sources of undefined behaviour
  • Explain how UB can make code disappear
  • Use sanitizers to catch UB before your users do
c++20
Testing
  • Write a unit test that fails for the right reason
  • Explain what property-based testing adds
  • Structure a project so tests run on every build
c++20
Debugging
  • Reduce a failing case to a minimal reproduction
  • Use a debugger's watchpoints and backtraces
  • Read a stack trace from a crash
c++20
Invariants and assertions
  • Identify a class invariant and where it can break
  • Use assert appropriately in debug builds
  • Explain the difference between a precondition and an invariant
c++20

Performance

ChapterYou should be able toStandard
What the compiler does
  • Read simple optimized assembly
  • Explain constant folding, inlining, and dead-code elimination
  • Compare -O0 and -O2 output for the same function
c++20
Measuring
  • Write a microbenchmark that is not optimized away
  • Explain why timing one run tells you nothing
  • Profile a program and find where the time goes
c++20
Cache and layout
  • Explain what a cache line is and why locality matters
  • Compare array-of-structs with struct-of-arrays
  • Predict which of two loops is faster and verify it
c++20
Zero-cost, examined
  • Show that a range pipeline compiles to the same code as a loop
  • Identify an abstraction that does cost something
  • Explain what zero-cost does and does not promise
c++20
Copies and elision
  • Explain guaranteed copy elision and NRVO
  • Find an unnecessary copy in a code review
  • Explain why returning std::move(x) can be worse than returning x
c++20
Inlining and linking
  • Explain what inline actually means
  • Describe link-time optimization and its cost
  • Reduce binary size and build time deliberately
c++20

Concurrency

ChapterYou should be able toStandard
Threads
  • Start and join a thread correctly
  • Explain what happens if a joinable thread is destroyed
  • Use jthread and stop tokens
c++20
Races and mutexes
  • Define a data race precisely
  • Protect shared state with a mutex and a lock guard
  • Explain how a deadlock forms and how to avoid one
c++20
Atomics
  • Use an atomic counter correctly
  • Explain sequential consistency versus acquire-release
  • Recognise when lock-free code is the wrong answer
c++20
Futures and tasks
  • Use std::async and futures appropriately
  • Explain why std::async's default launch policy is a trap
  • Structure work as tasks rather than threads
c++20
Coroutines
  • Explain what co_await transforms a function into
  • Write a simple generator coroutine
  • Describe where the coroutine frame is allocated
c++20

Building real software

ChapterYou should be able toStandard
Translation units
  • Explain the compile-then-link model
  • Fix a duplicate-symbol and an undefined-symbol error
  • State the one-definition rule and how to satisfy it
c++20
Modules
  • Write and consume a module
  • Explain what modules fix about headers
  • Assess whether your toolchain can use them yet
c++20
Build systems
  • Write a CMakeLists.txt for a small library and its tests
  • Explain target-based CMake and why globals are worse
  • Configure a debug and a release build
c++20
Dependencies
  • Add a dependency with FetchContent or a package manager
  • Explain the trade-offs of vendoring
  • Pin versions so a build is reproducible
c++20
Project: search index
  • Design a program from an informal specification
  • Choose data structures against measured requirements
  • Ship it with tests, a build file, and a README
c++20

Problem solving

ChapterYou should be able toStandard
Reading a problem
  • Read a problem's constraints and derive the operation budget they imply
  • Identify the edge cases a statement implies but does not list
  • Write a solution that reads input and writes output in the format required
c++20
Counting the work
  • Derive the complexity of a loop nest and confirm it by doubling the input
  • Find the hidden cost in a standard-library call inside a loop
  • Recognise when the constant factor rather than the exponent is the problem
c++20
Template and fast I/O
  • Measure what C++ stream I/O costs and know when it matters
  • Read every input shape a contest uses, including one with no count
  • Write a template that does not get in your way
c++20
Sorting and comparators
  • Write a comparator that is a valid strict weak ordering
  • Choose between sort and stable_sort on evidence
  • Compress a large value range into small indices
c++20
Binary search
  • Use lower_bound, upper_bound and equal_range correctly
  • Write a binary search whose invariant you can state
  • Recognise a problem where the answer itself can be searched for
c++20
Two pointers
  • Explain why two forward-moving indices give O(n) rather than O(n²)
  • Write a variable-size window that maintains a condition
  • Recognise the precondition a sliding window needs
c++20
Prefix sums
  • Answer range-sum queries in O(1) after an O(n) precomputation
  • Get the half-open index convention right, in one and two dimensions
  • Apply many range updates in O(1) each with a difference array
  • Recognise a sweep as a difference array over sparse coordinates
  • Use prefix sums where a sliding window is invalid
c++20
Monotonic stacks
  • Recognise the "nearest greater or smaller element" shape in a problem
  • State and maintain the invariant a monotonic stack keeps
  • Explain why the nested while loop is O(n) in total
  • Use previous-smaller and next-smaller spans to count subarrays
  • Choose the tie-breaking rule that avoids double counting
c++20
Monotonic deques
  • Maintain the maximum of a sliding window in O(1) amortised per step
  • State the two reasons an index leaves a monotonic deque
  • Compare the deque against a multiset and know what the log factor costs
  • Combine two deques to bound a window's spread
  • Use a deque over prefix sums where a window is invalid
c++20
Hashing and counting
  • Choose between an array, a hash map, an ordered map, and sorting
  • Explain why std::unordered_map can degrade to O(n) per operation
  • Write a custom hash that resists an anti-hash test
  • Use a custom hash or a packed key for pair and tuple keys
  • Know what std::multiset's two erase overloads do
c++20
Recursion
  • Write a search as choose / explore / un-choose and keep the state consistent
  • Prune a search at the moment a partial solution becomes invalid
  • Measure the cost of a recursive frame and know your depth budget
  • Recognise when overlapping subproblems make memoisation apply
c++20
Bitmasks
  • Represent a subset as an integer and enumerate all of them
  • Use the standard bit intrinsics instead of hand-rolled loops
  • Enumerate every submask of every mask in 3^n rather than 4^n
  • Generate distinct permutations and combinations without writing a recursion
c++20
Greedy
  • State a greedy algorithm as a choice rule plus a claim
  • Test a greedy rule against brute force before trusting it
  • Prove a greedy optimal with an exchange argument
  • Recognise the problems where greedy is provably wrong
c++20
Divide and conquer
  • Recognise the split / solve / combine shape and its recurrence
  • Count inversions in O(n log n) by piggy-backing on a merge
  • Choose a base-case cutoff by measurement
  • Halve an exponent instead of decrementing it
  • Know when divide and conquer is the wrong tool
c++20
Meet in the middle
  • Recognise the n around 40 constraint as a meet-in-the-middle signal
  • Enumerate half the input and combine with sorting or hashing
  • Choose between binary search, two pointers, and a hash map for the combine
  • Judge when the memory cost makes the technique unavailable
c++20
Representing graphs
  • Choose between an adjacency list, a matrix, and an edge list
  • Build a compressed adjacency structure in one pass
  • [object Object]
  • Treat a grid as a graph without materialising it
c++20
BFS
  • Write BFS and know why it gives shortest paths in an unweighted graph
  • Mark vertices when they are enqueued, and know what it costs not to
  • Seed the queue with many sources to get "distance to the nearest"
  • Use a deque for 0/1 edge weights instead of a heap
c++20
DFS
  • Write DFS iteratively and know when the recursive form will overflow
  • Count connected components
  • Detect a cycle in a directed graph with three colours
  • Find bridges with entry times and low-links
  • Use entry/exit intervals as an ancestor test
c++20
Topological order
  • Produce a topological order with Kahn's algorithm and with DFS
  • Detect a cycle from the length of Kahn's output
  • Get the lexicographically smallest order with a heap
  • Write a DP over a DAG in topological order
c++20
Union-Find
  • Implement find with path compression and union by size
  • Measure what each optimisation is worth
  • Maintain component counts and sizes as edges arrive
  • Answer deletion queries offline by running time backwards
  • Encode a two-sided constraint by doubling the vertices
c++20
Dijkstra
  • Write Dijkstra with a priority queue and lazy deletion
  • Explain why a negative edge breaks it, with a four-vertex counterexample
  • Reconstruct a shortest path and count how many there are
  • Layer the graph to answer "with at most k free moves"
c++20
Negative weights
  • Relax every edge n-1 times, and detect a negative cycle with one more round
  • Mark the vertices that have no shortest path at all
  • Write Floyd-Warshall with the intermediate vertex in the outermost loop
  • Choose between all-pairs Floyd-Warshall and n runs of Dijkstra
c++20
Spanning trees
  • Write Kruskal with union-find and Prim with a heap
  • Say why the greedy choice is safe, using the cut property
  • Show that an MST does not contain shortest paths
  • Use the MST to answer bottleneck questions
c++20
Tree DP
  • Write a subtree DP as one iterative post-order sweep
  • Derive a rerooting transition and answer for every vertex in linear time
  • Handle a merge that has no inverse, using the runner-up
  • Recognise when a problem is asking you to reroot
c++20