Ch2.9: References

What is a Reference?

A reference in C++ is an alias for another object. It does not create a new object; it simply provides another name for an existing one. In this chapter, we only cover lvalue references.

Syntax

A reference is declared using the & symbol after the type. It must always be bound to an existing object at initialization:


#include <cstddef>

::std::size_t x{42zu};
::std::size_t& ref{x}; // ref is a reference bound to object x

Here, ref is not a separate object. It is another name for x.

Basic Behavior


#include <cstddef>

::std::size_t a{10zu};
::std::size_t& r{a}; // r bound to object a

r = 20zu; // modifies object a, because r refers to a
// now a == 20

Assigning through the reference changes the original object. References must always be initialized when declared and cannot be reseated.

Const References

You can also declare a reference as T const&. This means the reference cannot be used to modify the original object.


#include <cstddef>

::std::size_t b{30zu};
::std::size_t const& cr{b}; // const reference bound to object b

// cr = 40zu; // error: cannot assign through const reference

Lifetime Extension with T const&

A special rule in C++: when you bind a T const& to a temporary object, the lifetime of that temporary is extended to match the lifetime of the reference.


#include <cstddef>

::std::size_t const& r{42zu}; // binds to a temporary object
// The temporary object lives as long as r does

Without this rule, the temporary object would be destroyed at the end of the full expression, leaving the reference dangling. Lifetime extension makes T const& safe to use with temporaries.

Beware of T &a, b;

A common mistake is declaring multiple objects in one line with a reference:


#include <cstddef>

::std::size_t obj1{1zu};
::std::size_t obj2{2zu};

::std::size_t &a{obj1}, b{obj2};

In this declaration:

The & binds only to the name immediately following it. To declare both as references, you must write:


::std::size_t obj3{3zu};
::std::size_t obj4{4zu};

::std::size_t &c{obj3}, &d{obj4}; // both c and d are references

Best practice: declare one reference per line to avoid confusion.

Key Takeaways