Search code examples
c++exceptionnullpointerexceptiondereference

Safe pointer dereferencing in C++


In our code base we have many constructions like this:

auto* pObj = getObjectThatMayVeryRarelyBeNull();
if (!pObj) throw std::runtime_error("Ooops!");
// Use pObj->(...)

In 99.99% of cases this check is not triggered. I'm thinking about the following solution:

auto& obj = deref_or_throw(getObjectThatMayVeryRarelyBeNull());
// Use obj.(...)

Where deref_or_throw is declared as follows:

template<class T> T& deref_or_throw(T* p) {
  if (p == nullptr) { throw std::invalid_argument("Argument is null!"); }
  return *p;
}

That code is much clearer and works as I need.

The question is: am I reinventing the wheel? Is there some related solution in standard or boost? Or do you have some comments on the solution?

PS. Related question (with no satisfying answer): Is there a C++ equivalent of a NullPointerException


Solution

  • There are two ways of dealing with the "rare case of null-pointer" issue. First, it's the proposed exception solution. For this, the method deref_or_throw is a good thing, though I would prefer to throw a runtime_error, rather than an invalid_argument exception. You may also consider naming it NullPointerException, if you prefer that.

    However, if the ptr != nullptr case is actually a precondition to the algorithm, you should try your best to achieve 100% safety in having this non-null case. An assert is the appropriate thing in this case.

    Advantages of assert:

    • No cost at runtime in release mode
    • Makes it crystal clear to the developer, that he is responsible for this to never happen.

    Disadvantages of assert:

    • Potential undefined behavior in release mode

    You should also consider writing a method getObjectThatMayNeverBeNullButDoingTheSameAsGetObjectThatMayVeryRarelyBeNull(): A method that is guaranteed to return a non-null pointer to an object that is otherwise completely equivalent to your original method. However, if you can go the extra mile, I would strongly suggest to not returning a raw pointer anyway. Embrace C++11 and return objects by value :-)