References

A reference is another name for an existing variable. Unlike a pointer, it can't be null, can't be re-pointed, and needs no special syntax to use. References are how C++ functions modify their arguments and avoid copying large objects.

Declaring a reference

C++
#include <iostream>

int main() {
    int score = 70;
    int& alias = score;     // alias refers to score

    alias += 5;             // changes score
    std::cout << score << ' ' << alias << '\n';

    score = 100;
    std::cout << alias << '\n';
    std::cout << std::boolalpha << (&alias == &score) << '\n';   // same address
}
Output
75 75
100
true

int& reads "reference to int". A reference must be initialised when it's declared, and it then refers to that same object for its whole life — assigning to it assigns to the object.

References as parameters

A reference parameter lets a function change the caller's variable:

C++
#include <iostream>
#include <string>

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

void make_title(std::string& s) {
    if (!s.empty() && s[0] >= 'a' && s[0] <= 'z') s[0] = static_cast<char>(s[0] - 32);
}

int main() {
    int x = 3, y = 8;
    swap_values(x, y);
    std::string name = "grace";
    make_title(name);
    std::cout << x << ' ' << y << ' ' << name << '\n';
}
Output
8 3 Grace

(The standard library already provides std::swap.) Compare this with C, where you'd pass pointers and write *a everywhere.

const references: read without copying

Passing a std::string or std::vector by value copies all its contents. A const reference gives the function read-only access to the original — no copy:

C++
#include <iostream>
#include <string>
#include <vector>

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

int main() {
    std::vector<double> readings(1'000'000, 2.5);    // a million values
    std::cout << average(readings) << '\n';
}
Output
2.5

Trying to modify through a const reference is a compile error — the function's signature tells the caller their data is safe.

C++
#include <string>

void shout(const std::string& s) {
    s += "!";
}

int main() {
    shout("hello");
}
Compiler error
main.cpp:4:7: error: no viable overloaded '+='

A const reference can also bind to a temporary value, such as the string literal above or the result of an expression; a non-const reference can't.

References in loops

As lesson 11 showed, for (auto& x : v) modifies elements and for (const auto& x : v) reads them without copying.

Returning references

A function can return a reference to something that outlives the call — such as an element of a container passed in:

C++
#include <iostream>
#include <vector>

int& largest(std::vector<int>& values) {
    int* best = &values[0];
    for (int& v : values) {
        if (v > *best) best = &v;
    }
    return *best;
}

int main() {
    std::vector<int> scores{70, 95, 88};
    largest(scores) = 100;            // assign through the returned reference
    for (int s : scores) std::cout << s << ' ';
    std::cout << '\n';
}
Output
70 100 88

Never return a reference to a local variable: it's destroyed when the function returns, leaving a dangling reference. Compilers warn:

C++
#include <string>

const std::string& greeting() {
    std::string text = "hello";
    return text;
}

int main() {
    return static_cast<int>(greeting().size());
}
Compiler warnings
main.cpp:5:12: warning: reference to stack memory associated with local variable 'text' returned [-Wreturn-stack-address]

References vs. pointers

Reference T&Pointer T*
Can be nullNoYes (nullptr)
Can refer to something else laterNoYes
Syntax to useLike a normal variable*p, p->member
Use forParameters, range-for, returning access to existing objectsOptional references, re-pointing, low-level code (lesson 27)

Try it yourself

Write a function that normalises a vector of scores in place so the highest becomes 100.

Try it yourself · main.cpp
Edit the code, copy it into main.cpp, then compile and run it with c++ -std=c++20 -Wall main.cpp -o main && ./main. How to set up a C++ compiler
Output
80 60 100 90