References
A reference is a second name for an existing variable, written with & . References let functions modify the caller's data, avoid expensive copies with const& , and underpin the swap idiom. This lesson makes references click — and shows the dangling-reference trap to avoid.
Learn References in our free C++ course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.
Part of the free C++ course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
A reference is a nickname . If everyone in the office calls "Elizabeth" by "Liz", then "Liz" and "Elizabeth" are the same person — message either name and the same person hears it. You can't later decide that "Liz" now means a different colleague (a reference can't be rebound), and a nickname only makes sense once the person exists (a reference must be initialized). Passing by reference is like giving a colleague your real phone, not a photocopy of it — anything they change, you see when it comes back.
1. A Reference Is an Alias
Declare a reference with type& name = existing; . From then on the reference and the original are the same object — change one and the other changes too. References must be initialized when created and can never be made to refer to a different object afterward.
2. Pass by Value vs Pass by Reference
By default C++ copies arguments, so a function works on its own copy and the caller's variable is untouched. Take a parameter by reference ( int& n ) and the function operates on the caller's actual variable — changes persist after the call returns.
3. The Swap Idiom
Swapping two variables is the textbook reason references exist. Because both parameters are references, the function exchanges the caller's actual values — something impossible with pass-by-value. (The standard library's std::swap does exactly this for you.)
4. const References: Read Without Copying
For large objects like strings and vectors, copying them into a function is wasteful. A const reference ( const string& s ) gives the function direct, read-only access — no copy, and the compiler guarantees the function can't modify your data. This is the standard way to pass big objects you only need to read.
5. References in Range-Based Loops
In a range-based for , the loop variable is a copy by default. Use auto& to modify each element in place, and const auto& to read each element efficiently without copying. Choosing the right one is a small habit that pays off in correctness and speed.
Your turn. Make this function actually change the caller's variable:
These lines should increment a variable through a reference parameter and print the new value. Reorder so the program prints 6 .
Why: bump must be defined before main calls it. Inside main you declare score = 5 , then pass it to bump . Because the parameter is int& , n += 1 modifies the caller's score directly, so printing afterward shows 6 .
Predict the output before revealing each answer.
7 — r is an alias for a , so assigning through r changes a .
{'void f(int n) int x = 1; f(x); cout << x;'}
1 — n is a by-value copy, so the change inside f doesn't affect x .
{'vector v = ; for (auto& e : v) e += 5; cout << v[0] << v[1];'}
67 — auto& modifies each element in place, so the vector becomes {' '}.
Write a function that returns two results through reference out-parameters. Match the expected output in the comments.
Practice quiz
How do you declare a reference named r that aliases an existing int x?
- int& r = x;
- int* r = x;
- int r = &x;
- ref int r = x;
Answer: int& r = x;. A reference is written type& name = existing;, so int& r = x; makes r another name for x.
What does this print? int a = 3; int& r = a; r = 7; cout << a;
- 3
- 7
- 0
- It does not compile
Answer: 7. r is an alias for a, so assigning 7 through r changes a itself. It prints 7.
What does this print? void f(int n){ n = 99; } int x = 1; f(x); cout << x;
- 99
- 0
- 1
- It does not compile
Answer: 1. n is taken by value, so f works on a copy. The caller's x is unchanged and 1 prints.
Which parameter type lets a function modify the caller's variable?
- int n
- const int& n
- int& n
- const int n
Answer: int& n. A plain (non-const) reference int& n aliases the caller's variable, so changes persist after the call.
Why pass a large object as const std::string& s?
- It copies the string so the original is safe
- It reads the object without copying and forbids modifying it
- It allows the function to resize the string
- It is required by the compiler for all strings
Answer: It reads the object without copying and forbids modifying it. A const reference gives direct read-only access with no copy, and the const promises the function won't modify it.
Why must both swap parameters be references in void swap2(int& a, int& b)?
- References are faster to type
- So the function exchanges the caller's actual values, not copies
- Because swap can only take two arguments
- To avoid including <utility>
Answer: So the function exchanges the caller's actual values, not copies. Only by taking references does the function operate on the caller's real variables, making the exchange visible afterward.