Skip to content
  • References in Depth · C++

References in Depth

LearnViaNotes @learnvianotes· 3 min read

A reference is another name for an existing object. C++ has lvalue references (T&), const references (const T&) and rvalue references (T&&).

lvalue references

C++
#include <iostream>
#include <vector>
int main() {
    int x = 1;
    int& r = x;          // r is x
    r = 5;
    std::cout << x << ' ' << (&r == &x) << '\n';

    int y = 99;
    r = y;               // NOT re-binding: assigns 99 to x
    std::cout << x << '\n';

    std::vector<int> v{1, 2, 3};
    int& first = v[0];   // reference to an element
    first = 100;
    std::cout << v[0] << '\n';
}
Output
5 1
99
100
  • Must be initialised: int& r; is an error.

  • Can't be null and can't be re-seated to another object.

  • No “reference to reference”, no arrays of references, no pointers to references.

const references bind to temporaries

C++
#include <iostream>
#include <string>
std::string makeName() { return "temp"; }
int main() {
    const std::string& ref = makeName();   // lifetime of the temporary is extended to ref's scope
    const int& n = 42;                     // binds to a materialised temporary
    std::cout << ref << ' ' << n << '\n';
    // std::string& bad = makeName();      // error: non-const lvalue ref can't bind to an rvalue
}
Output
temp 42

lvalues and rvalues

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

void take(const std::string&) { std::cout << "lvalue (or const)\n"; }
void take(std::string&&)      { std::cout << "rvalue — can steal its guts\n"; }

int main() {
    std::string s = "hi";
    take(s);                     // lvalue
    take(std::string("tmp"));    // prvalue (temporary)
    take(s + "!");               // result of an expression is a temporary
    take(std::move(s));          // std::move casts s to an rvalue (xvalue)
}
Output
lvalue (or const)
rvalue — can steal its guts
rvalue — can steal its guts
rvalue — can steal its guts
ReferenceBinds to lvalueBinds to rvalueTypical use
T&YesNoModify caller's object
const T&YesYesRead-only parameter, no copy
T&&NoYesMove constructors, sink parameters
auto&& / T&& in a templateYesYesForwarding (“universal”) reference

Dangling references

C++ — reference invalidated by reallocation
#include <iostream>
#include <vector>
int main() {
    std::vector<int> v{1, 2, 3};
    int& ref = v[0];
    v.push_back(4);             // may reallocate: ref now refers to freed memory
    std::cout << ref << '\n';   // AddressSanitizer: heap-use-after-free
}

Can a reference be null?

What does it mean that std::move doesn't move anything?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report