CppReferences

References

A reference is an alias — another name — for an existing variable. It is not a separate object, does not have its own storage, and does not need to be dereferenced with special syntax. Once created, a reference and the variable it refers to are indistinguishable: any change through one is visible through the other, because they are the same piece of memory.

Declaring a reference
A reference is declared with an ampersand (&) after the type. It must be bound to a variable immediately — there is no such thing as an “empty” reference.

reference_basics.cpp

CPP
#include <iostream>

int main() {
    int score = 90;
    int& scoreRef = score;   // scoreRef is now another name for score

    scoreRef = 95;
    std::cout << score << std::endl;    // 95 — score changed too!

    score = 100;
    std::cout << scoreRef << std::endl; // 100 — they are the same variable

    return 0;
}
References must be initialized and cannot be reseated

Two rules make references fundamentally different from pointers. First, a reference must be bound to a variable at the moment it is declared. Second, once bound, a reference can never be made to refer to a different variable — assigning to a reference always assigns to the variable it already refers to, never rebinds it.

reference_rebind.cpp

CPP
int a = 1;
int b = 2;

int& ref = a;   // ref is bound to a
ref = b;        // this does NOT rebind ref to b!
                // it copies b's value (2) into a, since ref IS a.

// int& bad;    // compile error: references must be initialized
A reference is not a pointer in disguise
It is tempting to think of a reference as a pointer that automatically dereferences itself, but the “cannot be reseated” rule is the key difference. A pointer can be reassigned to point somewhere else at any time; a reference is permanently tied to the variable it was initialized with. This makes references simpler to reason about, but less flexible.
References vs pointers
References and pointers solve overlapping problems, but with different trade-offs. References are generally safer and easier to use correctly: they cannot be null, cannot be reseated, and need no special dereference syntax. Pointers are more flexible: they can be reassigned, can be null, and support pointer arithmetic. The dedicated Pointers vs References chapter later in this tutorial covers the full comparison and when to reach for each.
Pass by reference recap
The most common everyday use of references is passing arguments to functions without copying them — see the Parameters & Pass by Value/Reference chapter for a full walkthrough of void modify(int& value)-style function signatures.
Returning a reference from a function

Functions can return references too, which avoids copying the returned value. This is safe when the reference refers to something that will still exist after the function returns — such as a member of an object passed in by reference, or a static/global variable.

return_reference_ok.cpp

CPP
// Safe: returns a reference to an element that outlives the call
int& firstElement(int (&arr)[5]) {
    return arr[0];
}

int main() {
    int numbers[5] = {10, 20, 30, 40, 50};
    firstElement(numbers) = 999;   // modifies numbers[0] directly
    return 0;
}
Never return a reference to a local variable
A local variable is destroyed the moment the function returns. If you return a reference to it, you get a dangling reference — it refers to memory that no longer holds a valid object. Using it afterward is undefined behavior: it might appear to work by luck, or it might crash, or it might silently produce garbage values.

dangling_reference.cpp

CPP
int& dangerous() {
    int local = 42;
    return local;   // BUG: local is destroyed when the function returns
}                   // most compilers will warn about this

int main() {
    int& ref = dangerous();
    // ref now refers to destroyed stack memory — undefined behavior
    // std::cout << ref << std::endl;  // do NOT do this
    return 0;
}
  • References must be initialized when declared and can never refer to a different variable afterward.

  • Prefer references for function parameters that must always refer to a valid, existing object.

  • Never return a reference to a local variable, a temporary, or anything else that gets destroyed when the function ends.