Skip to content

Beginner · References, pointers, arrays and strings · topic 9 of 42 · 25 min

References: another name for a variable

Explanation

A reference is a second name (an alias) for an existing variable, written with & after the type. Passing by reference lets a function change the caller's variable, and passing by const reference lets it read a big object without copying it.

The problem references solve

In the last module you saw that C++ copies arguments by default (pass by value). That is a problem in two cases. First, when a function SHOULD change the caller's variable, such as adding money to a wallet. Second, when the argument is big, such as a list of 1,00,000 orders; copying it on every call wastes time and memory. References solve both.

What a reference is

cpp
int marks = 80;
int& ref = marks;   // ref is another name for marks

ref = 95;
std::cout << marks << '\n';   // 95
int& means "reference to int". ref and marks are the same box in memory.
Think of it like this: A reference is like a nickname. If your friend Rajesh is called "Raju" at home, giving Raju a sweet gives Rajesh a sweet: it is one person with two names. A copy would be a different person who looks the same.

Rules of references: a reference must be initialised when it is created (int& r; is an error), and it can never be changed to refer to a different variable later. Writing r = other; copies other's value INTO the variable r refers to.

Pass by reference

cpp
void addBonus(int& marks) {
    marks += 5;
}

void swapValues(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

int main() {
    int m = 80;
    addBonus(m);
    std::cout << m << '\n';          // 85

    int x = 1, y = 2;
    swapValues(x, y);
    std::cout << x << ' ' << y;      // 2 1
}
The parameter is a reference to the caller's variable, so changes are visible outside. (The standard library already has std::swap.)

Pass by const reference

cpp
#include <string>
#include <vector>

double average(const std::vector<int>& marks) {
    double sum = 0;
    for (int m : marks) sum += m;
    return marks.empty() ? 0 : sum / marks.size();
}

void greet(const std::string& name) {
    std::cout << "Namaste, " << name << '\n';
    // name += "!";   // error: name is const
}
const T& gives fast, read-only access: no copy, and the compiler stops accidental changes.
How to passCopy?Can change caller?Use for
T (by value)yesnosmall types: int, double, char, bool
T& (reference)noyes"output" parameters you mean to change
const T& (const reference)nonobig read-only inputs: string, vector, objects

References in range-for loops

cpp
std::vector<int> prices = {100, 200, 300};
for (int p : prices) p += 10;        // changes copies only
for (int& p : prices) p += 10;       // changes the real items: 110 210 310
for (const auto& p : prices) std::cout << p << ' ';
Use auto& to change items, const auto& to read big items without copies.
Careful: Never return a reference to a local variable. int& bad() { int x = 5; return x; } returns a reference to memory that is destroyed when the function ends. Using it is undefined behaviour (a "dangling reference"). Return by value instead; modern compilers make that cheap.

Common mistakes

  • Forgetting the & in a function that should change its argument, then wondering why nothing changes.
  • Passing a big std::vector or std::string by value in a loop that runs many times, which makes the program slow.
  • Trying to pass a literal to a non-const reference: addBonus(80) fails, because 80 is not a variable. A const reference can bind to a temporary value, so greet("Asha") works.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

References: another name for a variable · 1/6

References

In this lesson you will learn references: a second name for a variable that already exists.

Prefer a video by a teacher? Find free videos on “c++ references pass by reference const reference explained” on YouTube ↗

In real life: Updating a wallet balance

A payments app keeps each user's wallet balance in an object. The function that applies a cashback must change the real balance, so it takes the balance by reference. The function that prints a statement only reads the long list of transactions, so it takes them by const reference to avoid copying thousands of entries.

cpp
#include <iostream>
#include <vector>

void applyCashback(long long& balancePaise, long long cashbackPaise) {
    balancePaise += cashbackPaise;
}

void printStatement(const std::vector<long long>& txns) {
    for (long long t : txns) std::cout << t / 100 << " ";
    std::cout << '\n';
}

int main() {
    long long balance = 50000;            // Rs 500
    applyCashback(balance, 2500);         // + Rs 25
    std::cout << balance / 100 << '\n';   // 525
    printStatement({-12000, 50000, -3000});
}
Reference for the value we change, const reference for the data we only read.

Practice (0/4 done)

Task 1 · Question

int a = 10; int& r = a; r = 20; What is a?

Task 2 · Question

What does this print? void f(int x, int& y) { x = 0; y = 0; } int a = 5, b = 5; f(a, b); std::cout << a << b;

Task 3 · Question

Which is the best parameter type for a function that only prints a long std::string?

Task 4 · Practice

Write void splitBill(double total, int people, double& each, double& remainder) that fills each with the share rounded down to whole rupees and remainder with what is left. Call it from main and print both.

Quick quiz

Question 1

1.Which line does NOT compile?

Question 2

2.int a = 1, b = 2; int& r = a; r = b; b = 9; What is a?

Question 3

3.What is wrong with: const std::string& name() { std::string s = "Asha"; return s; }

Question 4

4.for (auto& p : prices) p *= 2; What happens to prices?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Which line does NOT compile?

Answer: int& r;

A reference must be bound to something when it is created.

int a = 1, b = 2; int& r = a; r = b; b = 9; What is a?

Answer: 2

r = b copies 2 into a. A reference cannot be re-pointed, so later changes to b do not affect a.

What is wrong with: const std::string& name() { std::string s = "Asha"; return s; }

Answer: It returns a reference to a local that is destroyed: a dangling reference

s dies when the function returns. Return std::string by value.

for (auto& p : prices) p *= 2; What happens to prices?

Answer: Every item is doubled

auto& binds to each real item, so changes stick.

int *const p = &x; Which is allowed?Related

Answer: *p = 5;

p itself is const, but the int it points to is not.

From Pointers and functions

const a = [1]; const b = a; b.push(2); What is a?Related

Answer: [1, 2]

a and b refer to the same array.

From References, copies and equality

Why does Rust forbid a &mut while & references exist?Related

Answer: So readers never see the value change under them (no data races)

Exclusive access for writers prevents data races and similar bugs.

From References and borrowing

Which parameter type lets a function read a String while the caller keeps it?Related

Answer: s: &String

A reference borrows the value without taking ownership.

From Ownership and functions

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 3 more topics in “References, pointers, arrays and strings” before its exam: Pointers, the stack and the heap, Arrays, std::array and a first look at std::vector, Text: C strings and std::string.
  2. Module 3 exam: References, pointers, arrays and strings · 12 questions · 20 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Classes, constructors and RAII. 42 topics left in the course before the final exam.

← Previous: Overloading, default arguments and recursion