References vs. Pointers, In Depth

Course 1 · Ch 8
References vs. Pointers, In Depth
C++ solves C's raw-pointer ergonomics problem — but not, on its own, C's safety problem

cpp1-2 introduced references structurally. This chapter is the practical guidance — when to reach for each — and the honest comparison against what Rust's own references actually guarantee.

Recap: The Structural Differences

PropertyReferencePointer
Can be nullnoyes
Can be reassignedno — bound permanentlyyes
Must be initialized immediatelyyesno

When to Use a Reference

Primarily function parameters: passing a large object by reference avoids an expensive copy while still letting the function read or modify the caller's actual object. Return types too — but never return a reference to a local variable; that's the exact reference-shaped version of c1-7's own dangling-pointer warning.

const Reference — Pass-By-Reference Without Copying, Safely

const T& is the real, idiomatic C++ default for passing anything nontrivial into a function — it avoids the copy plain pass-by-value would make, while const guarantees the function can't accidentally modify the caller's object. Genuinely the most common parameter-passing pattern in real C++ code.

void print_name(const std::string &name) { std::cout << name << std::endl; // no copy made, and name can't be modified here }

When to Use a Pointer

  • "No object" (null) is a genuinely valid state to represent
  • The thing being pointed to needs to be reassigned to point elsewhere later
  • Pointer arithmetic — iterating a raw array, exactly c1-6/c1-7's own territory
  • Ownership semantics via smart pointers — previewed for Course 2

Contrasted With Rust's Borrow Rules

Rust's &/&mut references are checked at compile time by the borrow checker for aliasing rules — you cannot have a mutable reference and any other reference to the same data alive simultaneously. C++ references have none of these guarantees enforced at all: a const T& and a plain T& to the same object can coexist freely, and nothing stops two non-const references from both mutating the same data unsafely — including from two different threads, tying directly to cpp3-4's own concurrency chapter. This is a real, genuine gap this course's own framing has been building toward: C++ references solve C's raw-pointer ergonomics problem — no dereference syntax, no null, no rebinding — but not its safety problem.

ConceptC++ ReferenceC++ PointerRust Reference
Aliasing rules enforced?nonoyes — compile-time borrow checking
Mutable + shared reference coexistingallowed, uncheckedallowed, uncheckedcompile error
Ergonomics vs. a raw pointerbetter — no null, no dereference syntaxn/abetter, and safety-checked
"const reference unless you have a reason not to" is close to a universal default
For any parameter type larger than a machine word, passing by const T& is the idiomatic starting point in real C++ — deviate only with a specific reason (needing to modify the caller's object, or genuinely wanting a cheap copy for a small type).
Returning a reference to a local variable dangles — with nothing marking it as such
The function's local storage is gone the instant it returns; the reference is left referring to memory that's already invalid, with no compiler error and no visible sign anything is wrong at the call site — exactly c1-7's own dangling-pointer warning, now in reference form.

Coding Challenges

Challenge 1

Write a function that takes a std::string by const reference and prints its length. Call it with a string literal and confirm no copy-related side effects are needed to make it work.

📄 View solution
Challenge 2

Write a function that deliberately returns a reference to one of its own local variables. Explain what happens when the caller tries to use the returned reference, tying your answer to c1-7's own dangling pointer material.

📄 View solution
Challenge 3

Explain precisely what Rust's borrow checker would reject that C++ freely allows, using a concrete scenario involving a mutable reference and a second reference to the same data — and why this specific gap is described as C++ solving pointer "ergonomics" but not "safety."

📄 View solution

Chapter 8 Quick Reference — Almost Course 1 Complete

  • Use a reference for function parameters/return values tied to an object that already exists elsewhere
  • const T& — the idiomatic default: avoids a copy, guarantees no mutation
  • Use a pointer when null is valid, reassignment is needed, or for raw pointer arithmetic
  • Never return a reference to a local variable — the exact dangling-pointer bug, in reference form
  • C++ references have no compile-time aliasing guarantees — a real, genuine gap vs. Rust's borrow checker
  • Next chapter: namespaces and the standard library tour — closing Course 1