Last time we covered pointer arguments, and that article was applicable to C and C++. C++ introduced true pass-by-reference semantics.
f( O & )
f( const O & )
f(O &)
Previously we were careful to note that passing a pointer to a function was still only pass-by-value. The pointer was copied, and then the function was free to use that pointer to modify the underlying object. That was how C provided the utility of pass-by-reference without actually having to implement it. C++ lets us declare a real reference type. We can then use the variable in the function as we would if it were inline in the caller.
void f(O &p) {
p.modify();
}
Barring the different syntax (“.
†instead of “->
â€), there is one fundamental difference between pass-by-reference and pass-by-pointer: null is not a valid value. You can only pass a reference to an object that exists. It’s not possible to call f(nullptr)
since nullptr
is a pointer not an object. It’s not possible to call f(*nullptr)
, since dereferencing nullptr
is illegal. Therefore f()
doesn’t need to check for nullptr
itself.
We’re also cutting off any ability for f()
to affect the lifetime of p
. Whereas in the f(O*)
case, f()
could modify the object and delete it; in the f(O&)
case, f()
cannot delete
the object, since delete
requires a pointer (I’m ignoring the insane case of delete &p
).
That fact makes f(O&)
far more attractive as a “modifies O†function declaration that f(O*)
. In fact, if you find yourself writing f(O*)
, think very carefully about whether you really have got the correct form.
f(const O &)
This is an easy one; excepting the change of syntax, this is identical to f(const O *)
saving the fact that it’s not possible to pass nullptr
to it.
Like f(O*)
and f(O&)
, there is reason to pick between f(const O*)
and f(const O&)
:
f(const O&)
-
f()
queries anO
f(const O*)
-
f()
queries anO
with a fallback if thisO
doesn’t exist.
Choose between them as appropriate for your application. On the whole though, you should prefer f(const O&)
, since you should only work with objects that exist – why would you even call f()
if you had nothing to call it with?
Next time, C++11.