Worked examples — References — lvalue references, difference from pointers
The scenario matrix
Before solving anything, let us enumerate what "every case" even means for references. A reference has only a few axes it can vary along, so the matrix is small and we can genuinely cover all of it.
| Cell | Scenario class | What varies | Covered by |
|---|---|---|---|
| C1 | Bind to a named variable (the happy path) | write-through, address identity | Example 1 |
| C2 | sizeof / identity — is there a second box? |
object identity | Example 2 |
| C3 | Illegal binding — literal / temporary to int& |
rvalue vs lvalue | Example 3 |
| C4 | const T& binds a temporary + lifetime extension |
const, rvalue | Example 4 |
| C5 | Reference parameter (pass-by-reference) vs by-value | copy vs alias | Example 5 |
| C6 | Reference to an array element / chained alias | aliasing a sub-object | Example 6 |
| C7 | Degenerate / dangling — return reference to a local | lifetime = 0 after return | Example 7 |
| C8 | Reference member in a struct — must init in ctor list | binding at construction | Example 8 |
| C9 | Real-world word problem — a "score tally" | applied aliasing | Example 9 |
| C10 | Exam twist — reference reassignment looks like reseat | = on an alias |
Example 10 |
The "signs and quadrants" of a trig topic become, for references, these binding categories: lvalue vs rvalue, const vs non-const, lives-long-enough vs dies-early. Every example below is tagged with its cell.
Example 1 — The happy path (Cell C1)
Example 2 — Is there a second box? (Cell C2)
Example 3 — Illegal binding: literal to int& (Cell C3)
int& bad = 5; // ERRORForecast: what category of value is 5, and why does that matter?
5is an rvalue — Why this step? An rvalue is a value with no stable storage location you can alias — a literal, a temporary. A non-constint&demands an lvalue (a named box) to glue onto.- There is nothing to alias, so binding fails at compile time. The fix is either a real variable (
int five = 5; int& r = five;) or aconst int&(next example).
Verify: conceptual — the compiler rejects it. We simulate the rule numerically: 5 has no address, whereas a variable does. See the const rescue below.
Example 4 — const T& binds a temporary (Cell C4)
const int& r = 3 + 4; // (1) legal!
int out = r; // (2) what value?Forecast: 3 + 4 is a temporary — does r dangle instantly, or survive?
const int& r = 3 + 4;— Why this step? Aconst T&may bind a temporary and extends its lifetime to match the reference's scope. The temporary7now lives as long asrdoes.int out = r;— Why this step? Reading throughryields the still-alive7. Because it isconst, we may read but never write (r = 9;would fail — see const correctness).
Verify: out == 7. The lifetime extension is what makes void print(const std::string&) accept print("hi") — the temporary string lives through the call. ✓
Example 5 — Reference parameter vs by-value (Cell C5)
void addTen_ref(int& n) { n += 10; }
void addTen_val(int n) { n += 10; }
int x = 5, y = 5;
addTen_ref(x); // x = ?
addTen_val(y); // y = ?Forecast: which of x, y changes?
addTen_ref(x)— Why this step? The parameternis an alias of the caller'sx(pass-by-reference).n += 10writes the caller's box →xbecomes 15.addTen_val(y)— Why this step? Herenis a copy (pass-by-value).n += 10edits the copy; the caller'sybox is untouched →ystays 5.

Verify: x == 15, y == 5. Reference = same box (caller changes); value = private copy (Pass-by-value vs Pass-by-reference). ✓
Example 6 — Reference to an array element (Cell C6)
char letters[4] = {'a','b','c','d'};
char& third = letters[2]; // alias to 'c'
third = 'Z';
char result = letters[2]; // ?
size_t sz = sizeof(third); // ?Forecast: guess result and sz — is sz 1 or a pointer size?
char& third = letters[2];— Why this step?letters[2]is a genuine lvalue (a real cell with an address), so binding is legal.thirdnow names that exact cell.third = 'Z';— Why this step? Writing through the alias overwrites the cell →letters[2]becomes'Z'.sizeof(third)— Why this step?sizeofsees through the reference tochar, giving 1, disproving the "reference is always an 8-byte pointer" myth from Example 2.
Verify: result == 'Z' (its ASCII code is 90), sz == 1. ✓
Example 7 — Dangling: reference to a local (Cell C7)
int& makeBad() {
int local = 42;
return local; // DANGER
}
int z = makeBad(); // reads a dead boxForecast: is the value 42 reliable? (Trick question.)
return local;— Why this step? We return a reference aliasinglocal. Butlocalis destroyed the instantmakeBadreturns; its box is reclaimed.int z = makeBad();— Why this step? We now read through a reference to a dead object → undefined behaviour. It may print 42, may print garbage, may crash. Never rely on it.- Fix: return by value (
int makeBad()), or return a reference only to something that outlives the call — a member, astatic, or a parameter passed in (Dangling references and lifetime).

Verify: conceptual — UB has no defined value. We instead verify the safe version: returning local's value by copy would correctly give 42.
Example 8 — Reference member (Cell C8)
struct Watcher {
int& target; // reference member
Watcher(int& t) : target(t) {} // MUST bind in init list
void bump() { target += 1; }
};
int counter = 100;
Watcher w(counter);
w.bump();
w.bump();
int c = counter; // ?Forecast: guess counter after two bumps.
Watcher(int& t) : target(t) {}— Why this step? A reference member must be initialized in the constructor's initializer list — you cannot writetarget = t;in the body, because that would be reseating an already-bound reference, which is forbidden.w.bump(); w.bump();— Why this step? Eachbumpwrites throughtarget, an alias ofcounter. Two increments →counter= 102.
Verify: c == 102. The alias reaches straight into the caller's counter. ✓
Example 9 — Word problem: shared score tally (Cell C9)
A game keeps int homeScore. A helper awardGoals gives points directly into the scoreboard without any copy. Home starts at 3, we award 2 then 4.
void awardGoals(int& board, int goals) { board += goals; }
int homeScore = 3;
awardGoals(homeScore, 2);
awardGoals(homeScore, 4);
int final = homeScore; // ?Forecast: what is the final score?
int& board— Why this step? We want the helper to edit the real scoreboard, not a throwaway copy — so we alias it by reference.- First call
+= 2→ 5. Second call+= 4→ 9. Each call scribbles the one shared box.
Verify: final == 3 + 2 + 4 == 9. Units: goals are dimensionless counts, sum is a count → consistent. ✓
Example 10 — Exam twist: assignment vs reseat (Cell C10)
alias = other; re-point the alias?
int a = 1, b = 2;
int& alias = a; // alias names a
alias = b; // TWIST: does alias now name b?
b = 99; // change b
int va = a; // ?
int vb = b; // ?Forecast: after alias = b;, does changing b also change a?
int& alias = a;— Why this step? Binding:aliasis permanently glued toa's box.alias = b;— Why this step? This is the trap. It is not a reseat — it is an assignment through the alias. It readsb's value (2) and stores it intoa's box. Nowa == 2, butaliasstill namesa.b = 99;— Why this step? This editsb's own box, whichalias/ahave nothing to do with. Soastays 2.

Verify: va == 2, vb == 99. A reference can never be reseated; the = moved a value, not the alias. ✓
Active recall
Recall Cover the answers
Does sizeof(int&) on a double& t give 8 because of a hidden pointer? ::: No — it gives sizeof(double)=8 because sizeof sees the referent; the pointer myth just coincides here.
Why does const int& r = 3+4; survive but int& r = 3+4; fail? ::: const ref binds and lifetime-extends the temporary; non-const ref needs a named lvalue.
After int& alias=a; alias=b;, does alias now name b? ::: No — it copied b's value into a; the alias still names a (no reseat).
Why must a reference member be set in the constructor's init list? ::: You can't reseat a reference, so it must be bound at construction, not assigned in the body.
What is the value of a reference returned to a destroyed local? ::: Undefined — the object is dead; never rely on it.
"Bind once, alias always; = moves values, not labels; dead boxes bite."
Connections
- Pointers in C++ — the reseatable, nullable cousin used to contrast every cell
- Pass-by-value vs Pass-by-reference — Example 5's copy-vs-alias split
- const correctness — Example 4's
const T&rescue - Rvalue references and move semantics — where rvalue binding (Cell C3/C4) goes next
- Dangling references and lifetime — Example 7's trap
- sizeof and object identity — Example 2 and 6