Checking pointers before using? necessity and alternatives, C++ UE4

1.6k Views Asked by At

I'm new to UE4, and I encountered the general pattern of checking each pointer before using it, for example:

AActor *pActor = getOwner(); 
if(pActor){
   pActor->SOME_FUNCTION();
}

I'm aware to the fact that crashes are awful in terms of user experience, and that it is always advised to write code with maximum robustness, but are there well-known cases in which the pattern is really useful? (for example in theoretically safe settings, such as a pointer set to GetOwner()).

And if so, are there any common alternatives for this? (perhaps making use of smart pointers?)

EDIT: In my question I wanted to get an answer regarding UE4 specifically, since I encountered a source relating to UE4 only, which advised me to check pointers, although I wasn't sure about its necessity and in which pattern.

2

There are 2 best solutions below

0
On BEST ANSWER

If you are not absolutely guaranteed to receive a valid pointer from a function that returns a pointer, you need to check that pointer. In the case of libraries that are black boxes (you don't own the code), you can perhaps take the word of the library author that the pointer will always be valid, but based on a comment above, that does not appear to be the case here.

Interestingly enough, in the C++ Core Guidelines: http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-gsl

There is a template in the Guidelines Support Library called not_null<T> which can be used to encapsulate a pointer to provide the guarantee that the pointer is never NULL.

12
On

Since this is tagged C++, there is an obvious alternative for a pointer that must not be NULL: a reference. (see basic considerations or technical details for more information).

If you stay with pointers, you have - by definition - to deal with the possibility that each and everyone of them is NULL.


Update: A pretty silly example:

AActor & get_existing_owner() 
{
    AActor * pActor = getOwner(); 
    check(pActor);
    return *pActor;
}

Please note that this changes the behavior of your code in case getOwner actually returns nullptr some time (cf. UE Assertions). Then you could write somewhere else (without further checks):

get_existing_owner().some_function();

Obviously above get_existing_... checking method could be generealized / reused for other pointers.