Skip to content

/compare/cpp/pointer-vs-reference

C++ pointer vs reference: when to use T* or T&

The commands on this page have not been executed by our verification runner yet.updated
tool
C++
compares
pointer (T*) vs reference (T&)

A C++ reference (T&) is an alias for an existing object: it must be initialized, cannot be null in valid code and cannot be changed to refer to another object. A pointer (T*) holds an address: it can be null, can be reassigned, supports arithmetic, and needs * or -> to reach the object. Use a reference when there is always exactly one object (most function parameters); use a pointer when "no object" is a valid case or the target changes; use smart pointers (std::unique_ptr, std::shared_ptr) when the code owns the object.

Differences

Pointer T*Reference T&
Can be nullYes (nullptr)No
Must be initializedNo (but should be)Yes
Can be reseatedYes, p = &otherNo: assignment changes the referred object
Access syntax*p, p->memberr, r.member
ArithmeticYes (p + 1, p[i])No
Pointer to it / array of themYesNo arrays of references
OwnershipRaw pointers should not own; use smart pointersNever owns

Example

cpp
#include <iostream>
#include <string>

void set_name(std::string& s) { s = "grace"; }                  // must get an object
void maybe_set_name(std::string* s) { if (s) *s = "linus"; }   // may get nullptr
std::size_t length(const std::string& s) { return s.size(); } // read-only, no copy

int main() {
    std::string name = "ada";
    set_name(name);
    maybe_set_name(&name);
    maybe_set_name(nullptr);

    std::string other = "ken";
    std::string& r = name;
    r = other;              // copies "ken" into name; r still refers to name
    std::string* p = &name;
    p = &other;             // p now points to other
    std::cout << name << ' ' << *p << ' ' << length(name) << '\n';   // ken ken 3
}

Guidelines for parameters

  • const T& for inputs that are expensive to copy; plain T for cheap types such as int or std::string_view.
  • T& for parameters the function modifies.
  • T* when the argument is optional (nullptr means "none"), or use std::optional<std::reference_wrapper<T>> if you prefer to be explicit.
  • std::unique_ptr<T> by value to transfer ownership; never delete an object you received as a raw pointer or reference.

Sources