Functionally, all three of these work:
pass an int
and change the return type to int
so you can return the new value, usage: x = f(x);
- when you plan to set the value without needing to read the initial value, it's much better to use a function like
int DoSomething();
so the caller can just say int x = f();
without having to create x
on an earlier line and wondering/worrying whether it needs to be initialised to anything before the call.
pass an int&
and set it inside the function, usage: int x; x = ? /* if an input */; f(x);
pass an int*
and set the pointed-to int
inside the function, usage: int x; x = ?; f(&x);
most efficient on memory and performance so I'm not copying the variable around
Given the C++ Standard doesn't dictate how references should be implemented by the compiler, it's a bit dubious trying to reason about their characteristics - if you care compile your code to assembly or machine code and see how it works out on your particular compiler (for specific compiler commandline options etc.). If you need a rule of thumb, assume that references have identical performance characteristics to pointers unless profiling or generated-code inspection suggests otherwise.
For an int
you can expect the first version above to be no slower than the pointer version, and possibly be faster, because the int
parameter can be passed and returned in a register without ever needing a memory address.
If/when/where the by-pointer version is inlined there's more chance that the potentially slow "needing a memory address so we can pass a pointer" / "having to dereference a pointer to access/update the value" aspect of the pass-by-pointer version can be optimised out (if you've asked the compiler to try), leaving both versions with identical performance....
Still, if you need to ask a question like this I can't imagine you're writing code where these are the important optimisation choices, so a better aim is to do what gives you the cleanest, most intuitive and robust usage for the client code... now - whether that's x = f(x);
(where you might forget the leading x =
), or f(x)
where you might not realise x
could be modified, or f(&x)
(where some caller might think they can pass nullptr
is a reasonable question in its own right, but separate from your performance concerns. FWIW, the C++ FAQ Lite recommends references over pointers for this kind of situation, but I personally reject its reasoning and conclusions - it all boils down to familiarity with either convention, and how often you need to pass const
pointer values, or pointer values where nullptr
is a valid sentinel, that could be confused with the you-may-modify-me implication hoped for in your scenario... that depends a lot on your coding style, libraries you use, problem domain etc..