Pointer Implications (C++)

By | 2013-08-06

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 an O

f(const O*)

f() queries an O with a fallback if this O 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.

Leave a Reply