Skip to content
Free public beta until December 4, 2026: every course is open, no card needed. After that, the first chapter of each course stays free and full access is a one-time $39 ($19 for up to 100 founding members chosen for helpful feedback). Your progress is kept. How the beta works

Every way to pass an argument

By value, by reference, by const reference, by pointer, as a view, or by handing ownership over. What each promises, and which to pick.

Ask what the function does with the argument, and stop at the first line that fits.

  • Only reads a small value (int, double, char, bool) → pass it by value: int n.
  • Only reads text → std::string_view. Only reads a run of elements (from a vector, a std::array or a plain array) → std::span<const T>.
  • Only reads anything else that's big → const T&.
  • Keeps its own copy anyway (stores it, or changes a copy and returns it) → take it by value and let the call make the copy.
  • Must change the caller's object, which always exists → T&. Changing elements in place but never how many there are → std::span<T>.
  • The object might not be there → T* or const T*, with nullptr meaning "none". A raw pointer never owns.
  • Takes ownership of a heap object → std::unique_ptr<T> by value; the caller writes std::move(p).

A reference or a view must not outlive the object it refers to. Never store one past the call unless you can prove the object lives longer.

The basic three

The function gets a photocopy. Changes stay inside the function.

The parameter is another name for the caller's object, so changes show up in the caller.

The rule-of-thumb table for parameters, and its one exception, a function that copies anyway.

Pointers and views

A pointer can be null and can be re-pointed. A reference can't be either.

Accepts a std::string, a string literal or a char buffer, without copying. Cheap enough to pass by value.

One parameter replaces a pointer and a count, and accepts a vector, a std::array or a plain array.

Handing things over

The caller must std::move it in, which makes the hand-over visible at the call.

Why an overload taking T&& can steal from a temporary instead of copying it.

What not to do

The dangling-reference trap every reference and view shares.

The legacy parameter styles you'll meet in older code, next to their modern replacements.