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, astd::arrayor 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*orconst T*, withnullptrmeaning "none". A raw pointer never owns. - Takes ownership of a heap object →
std::unique_ptr<T>by value; the caller writesstd::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
Section
By value, a private copy
The function gets a photocopy. Changes stay inside the function.
Section
By reference, T&
The parameter is another name for the caller's object, so changes show up in the caller.
Section
By const reference, const T&
The rule-of-thumb table for parameters, and its one exception, a function that copies anyway.
Pointers and views
Section
Pointer or reference?
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.
Section
std::span for a run of elements
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.
Section
Rvalue references and std::move
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.