Foundations — Lambda expressions — capture list (by value, by reference)
Before you can read the parent note you must own about a dozen small ideas. This page builds each one from absolute zero, in the order they depend on each other. Nothing here uses a symbol before it is drawn.
1. int and friends — the basic types (what a box can hold)
The common built-in types you should recognise:
int→ a whole number (the default number type).double→ a number with a decimal point (like3.14).char→ a single character (like'A').bool→ a truth value:trueorfalse.
2. A variable is a labelled box in memory

Look at the figure: the name n is a sticky label, the box is a real location in memory (it has an address — a house number), and the value 10 is what currently sits inside. These are three different things, and the whole capture-list topic is about which of them a lambda grabs.
- The name is how your code refers to the box.
- The address is where the box physically is.
- The value is what is inside right now — and it can change later (
n = 99;swaps the contents).
3. = means "put into", not "is equal to"
This single distinction is what makes the parent's Example 1 (n=1 then n=99, lambda still prints 1) even possible to talk about: the box's contents were overwritten, but a copy taken earlier was not.
4. The address-of operator &n — "take the box's house number"
int n = 10;
&n; // an expression: the address (location) of the box n5. Scope — where a box exists, and when it dies

In the figure, the box x lives only inside the function make(). The moment make() returns, the whole shelf is cleared — x's box no longer exists. Anyone still holding the address (&x) of that box is now pointing at empty space.
6. A copy vs an alias (this is the whole topic)

The figure shows both side by side:
- Left (copy): two separate boxes. Change the original to
99; the copy still shows1. → This is capture by value[n]. - Right (reference
&): one box, two labels. Change through either label and both "see"99. → This is capture by reference[&n].
7. auto — "compiler, you name the type"
auto add = [](int a, int b){ return a + b; }; // its type is unnameable -> auto8. struct and brace-initialization — the box that holds many boxes
struct Point { // blueprint: two boxes bundled together
int x;
int y;
};
Point p{3, 4}; // make a Point; x gets 3, y gets 4 (brace-initialization)This matters because the next section's functor — and every lambda — is exactly such a struct, and its captured variables are its members, filled in with brace-init when the lambda object is born.
9. A function that lives inside a value: the functor
struct Adder {
int base; // a member box
int operator()(int x) const { return x + base; } // call syntax: a(5)
};
Adder a{10}; // brace-init: base gets 10 now
a(5); // 15 -- looks like a function call, is really a.operator()(5)10. WHEN the copy happens — at creation, not at call

Read the timeline in the figure left to right:
int n = 1;— the boxnholds1.auto f = [n]{ return n; };— creation: the copy is taken here, so the member box insidefis set to1and frozen.n = 99;— this overwrites the outside box only; the member copy insidefwas already made and is untouched.f()— call: it reads its own member box, which still says1.
11. const and mutable — the read-only lock and its key
This is the reason the parent says a by-value capture is read-only. The compiler generates the lambda's operator() const by default, so its member copy cannot be touched.

The figure shows the generated closure struct: members on top (the captures), a const operator() below. A padlock sits on the members because of const; the word mutable is the key that removes it.
12. The this pointer — capturing the enclosing object
struct Widget {
int value = 5;
auto getReader() {
return [this]{ return value; }; // [this] -> lambda can see value
}
};13. Generalized captures — init-capture and move-capture (C++14)
int y = 7;
auto f = [x = y + 1]{ return x; }; // member x starts at 8auto data = std::make_unique<int>(10);
auto job = [p = std::move(data)]{ return *p; }; // ownership moved into the lambda
// data is now empty; p inside the lambda owns the int14. Putting the notation together
Prerequisite map
Everything on the left is a "box" idea; everything feeding H (the lambda) is what the parent page silently assumes you already own.
Equipment checklist
Recall Self-test: am I ready for the parent note?
What does the type word int tell the compiler? ::: That the box is a whole-number box (an integer) — its size and the kind of value it holds.
What are the three separate things a variable has? ::: A name (label), an address (where it lives), and a value (what is inside now).
What does n = 99; actually do? ::: It overwrites the box named n with the value 99 (assignment, a command — not equality).
What does the expression &n produce? ::: The address (memory location) of the box n — used by by-reference capture to remember where the box lives.
The symbol & has two jobs — what are they? ::: Before a name (&n) it means "address of"; glued to a type (int&) it means "reference / second name for a box".
What is a reference int&? ::: A second name for an existing box; no new box is made, and writing through it changes the original.
How is a copy different from a reference? ::: A copy is a brand-new independent box; changing the original never affects it.
What is scope, and what happens at the closing }? ::: The region where a box is alive; at } the box is destroyed and any saved address to it becomes invalid.
WHEN does a by-value capture copy the variable — at creation or at call? ::: At creation (when the lambda object is built), once; that frozen copy is why n=1; n=99; still prints 1.
Why must you write auto for a lambda's type? ::: Its real type is a compiler-generated name you cannot write out, so auto lets the compiler fill it in.
What is a struct, and what does a{10} do? ::: A struct bundles several member boxes under one name; a{10} builds the object and fills its members in order (brace-initialization).
What is a functor? ::: An object with operator() so it can be called like a function; captures become its members.
Why is a by-value capture read-only by default, and what fixes it? ::: The generated operator() is const, forbidding member changes; the keyword mutable cancels that const so the private copy becomes writable.
Does mutable change the original outside variable? ::: No — it only unlocks the lambda's internal copy; the original is untouched.
What does [this] capture, and what does [=] do about the object? ::: [this] stores the address of the current object so the lambda can reach its members; [=] in a member function also captures this (not a copy) — use [*this] to copy the object.
What does [x = std::move(q)] do? ::: An init/move-capture: it builds a fresh member x by moving ownership of q into the lambda (C++14), leaving q empty.
Decode [=, &b]. ::: Capture everything used by value (copy) except b, which is captured by reference.