References

Intermediate

Introduction

Functions normally work on copies. That is safe, but sometimes a function has to change the caller's variable, and copying a list of a million items on every call would be very wasteful. References solve both problems, and they appear in almost every real C++ program.

How it works

A reference is a second name for a variable that already exists. It is written with & after the type:

int x = 5;
int& r = x;
r = 9;          // x is now 9

A reference has to be connected to something when it is made, and it stays with that variable for life.

As parameters. With a plain int parameter, the function gets a copy. With int&, the parameter is another name for the caller's variable, so changes are seen by the caller.

Const references. Passing a vector or string by value copies every element. Passing by const vector<int>& costs almost nothing, and const guarantees that the function will not change it. This is the normal way of passing anything larger than a number.

In loops. for (int& x : v) makes x a reference to each element, so changing x changes the vector. Without the &, x is a copy.

You wantWrite
a small value, read onlyint x
to change the caller's variableint& x
a large value, read onlyconst string& s
#include <iostream>
#include <vector>
using namespace std;

int total(const vector<int>& v) {
    int sum = 0;
    for (int x : v) {
        sum += x;
    }
    return sum;
}

void add_to_all(vector<int>& v, int amount) {
    for (int& x : v) {
        x += amount;
    }
}

int main() {
    vector<int> v = {1, 2, 3};
    cout << total(v) << endl;
    add_to_all(v, 10);
    cout << total(v) << endl;
    return 0;
}
Open in compiler

Syntax

void reset(int& n) {
    n = 0;
}

int length(const string& s) {
    return s.size();
}

Example

#include <iostream>
using namespace std;

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

int main() {
    int x = 4, y = 9;
    swap_values(x, y);
    cout << x << " " << y << endl;
    return 0;
}
Open in compiler

Line by line

  1. a and b are references, so they are other names for the caller's variables.
  2. int temp = a; saves the first value.
  3. a = b; and b = temp; change x and y directly.
  4. main passes x and y with no special syntax.
  5. The values have been swapped when they are printed.

Expected result

9 4

In the real world

Passing by const& is one of the first things reviewers look for in C++ code, because needless copies are a common cause of slow programs. Standard library functions take most of their arguments this way.

Common mistakes

  • Forgetting the &, so the function changes only a copy.
  • Forgetting the & in a loop, so that changes are lost.
  • Returning a reference to a local variable, which no longer exists after the return.
  • Passing a large object by value when only reading it.

Best practices

  • Pass numbers and other small values by value.
  • Pass larger read-only objects by const&.
  • Use a plain reference only when the function really needs to change the value.

Summary

A reference is another name for a variable. Reference parameters let functions change their caller's variables, and const& passes large values with no copying. In a range-based loop, & lets you change the elements.

Quick check

1. After int x = 1; int& r = x; r = 7; what is x?
2. void f(int a) { a = 5; } After int n = 1; f(n); what is n?
3. What is the best way to pass a long string that will only be read?
4. for (int x : v) x = 0; What happens to v?

Key takeaways

  • A reference is another name for the same variable.
  • Use a plain reference when a function must change something.
  • Use const& to read a large object without copying it.

Practice problems for this lesson

My notes

Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.