CodeMIRAI
0 XP

References

3 min read 5 runnable examples Quiz included

A reference is another name for a variable that already exists. Whatever you do through the reference happens to the original.

A second name

C++
#include <iostream>
using namespace std;

int main() {
    int score = 10;
    int& ref = score;        // ref is another name for score
    ref = 25;
    cout << score << endl;
    score++;
    cout << ref << endl;
    cout << (&ref == &score) << endl;   // the same address: one variable
    return 0;
}
Output
25
26
1

int& ref = score; doesn't copy anything. ref and score are the same variable, so changing either changes both. Two rules:

  • A reference must be given its variable when it's created: int& r; on its own doesn't compile.
  • It can't be moved to another variable later. ref = other; copies other's value into score.

Passing by reference

C++
#include <iostream>
using namespace std;

void swapCopies(int a, int b) { int t = a; a = b; b = t; }
void swapRefs(int& a, int& b) { int t = a; a = b; b = t; }

int main() {
    int x = 1, y = 2;
    swapCopies(x, y);
    cout << x << " " << y << endl;
    swapRefs(x, y);
    cout << x << " " << y << endl;
    return 0;
}
Output
1 2
2 1

An ordinary parameter is a copy, so swapCopies swaps its own copies and the caller's variables don't move. A reference parameter is the caller's variable itself. This is how C++ functions change their arguments without the pointers C needs.

Returning more than one value

C++
#include <iostream>
using namespace std;

void minMax(const int values[], int n, int& lowest, int& highest) {
    lowest = highest = values[0];
    for (int i = 1; i < n; i++) {
        if (values[i] < lowest) lowest = values[i];
        if (values[i] > highest) highest = values[i];
    }
}

int main() {
    int temps[] = {21, 17, 25, 19, 30, 16};
    int lo, hi;
    minMax(temps, 6, lo, hi);
    cout << "Lowest " << lo << ", highest " << hi << endl;
    return 0;
}
Output
Lowest 16, highest 30

A function returns one value, but it can fill in several reference parameters. These are called output parameters.

const references: no copy, no changes

C++
#include <iostream>
#include <string>
using namespace std;

// const string&: the string isn't copied, and the function promises not to change it
int countVowels(const string& text) {
    int n = 0;
    for (char c : text)
        if (string("aeiouAEIOU").find(c) != string::npos) n++;
    return n;
}

int main() {
    string line = "References avoid copying";
    cout << countVowels(line) << endl;
    cout << countVowels("works with temporaries too") << endl;
    return 0;
}
Output
9
9

Passing a string or vector by value copies every character or element. A const reference passes the original instead, and const lets the compiler stop the function from changing it. It also accepts temporary values, like the string literal on the last line.

The rule of thumb: pass small types (int, double, char) by value, big ones by const&, and use a plain & only when the function is meant to change the argument.

Changing elements in a loop

C++
#include <iostream>
using namespace std;

int main() {
    int prices[] = {100, 250, 80};
    for (int p : prices) p *= 2;        // p is a copy: the array doesn't change
    for (int p : prices) cout << p << " ";
    cout << endl;

    for (int& p : prices) p *= 2;       // p is each element itself
    for (int p : prices) cout << p << " ";
    cout << endl;
    return 0;
}
Output
100 250 80 
200 500 160 

In a range-for loop, int p copies each element and int& p refers to it. GCC even warns about the first loop that p is set but never used: each copy is changed and thrown away. Use const auto& x to read big elements without copying them.

Never return a reference to a local

C++
int& broken() {
    int local = 5;
    return local;     // warning: reference to local variable 'local' returned
}

local is destroyed when the function returns, so the reference would point at nothing. Returning a reference is fine for something that outlives the call, such as a member of an object or an element of a container that was passed in.

References and pointers

  • A reference always refers to something; a pointer can be nullptr.
  • A reference can't be re-pointed; a pointer can change what it points to.
  • A reference uses the plain variable syntax; a pointer needs * and &.
Reference: another namePointer: a separate box42xrint &r = x;r and x are the same box42x&xpint *p = &x; can be null or re-pointed
A reference is an alias that must be bound at once and can't be re-seated; a pointer is its own variable holding an address.

Reach for references by default, and pointers when "nothing" or "something else later" are real possibilities.

Finished this lesson?Mark it complete to earn +20 XP and move your progress on.