SkillByAIOpen interactive version →

Lesson 8 / 25

Pointers and References

Use pointers and references safely and avoid dangling references.

Two ways to refer to an object

A reference (int& r = x;) is an alias for an existing object: it must be initialised, cannot be reseated to refer to something else and is never null. Use references for function parameters and for giving access to existing objects. A pointer (int* p = &x;) is an object holding an address: it can be null (nullptr, never NULL or 0 in modern code), reassigned, and must be dereferenced with *p or p->member. Use pointers when "no object" is a valid state or when you need to re-point. Pointer arithmetic moves through arrays (p + 1 is the next element), but going out of bounds is undefined behaviour. const interacts with pointers in two places: const int* p (pointer to const data) versus int* const p (const pointer). The main danger with both is dangling: a pointer or reference to an object whose lifetime has ended, such as returning a reference to a local variable, or keeping a pointer into a std::vector that later reallocates. Raw pointers in modern code should be non-owning observers; ownership belongs to smart pointers and containers.

References, pointers and two dangling bugs

Both bugs compile; both are undefined behaviour at run time.

#include <string>
#include <vector>

void basics() {
    int x = 10;
    int& r = x;          // alias: r and x are the same object
    r = 20;              // x is now 20

    int* p = &x;         // address of x
    *p = 30;             // x is now 30
    p = nullptr;         // pointer can be null and reseated; a reference cannot
}

const std::string& bad_name() {
    std::string local = "temporary";
    return local;        // BUG: returns a reference to a destroyed local (dangling)
}

void bad_vector() {
    std::vector<int> v{1, 2, 3};
    int* first = &v[0];
    v.push_back(4);      // may reallocate and move all elements
    // *first = 99;      // BUG: first may now dangle
}

A nickname and an address slip

A reference is a nickname for a person: always refers to the same person and cannot exist without them. A pointer is a slip of paper with an address: it can be blank, rewritten, or still point to a house that has been demolished.

Quick check: Which statement about C++ references is true?

  • A reference can be null
  • A reference can be reseated to refer to another object
  • A reference stores a copy of the object
  • A reference must be initialised and always refers to the same object
Answer

A reference must be initialised and always refers to the same object — References are aliases bound at initialisation; they cannot be null or reseated.