IsValid best practices?


I’m looking for best practices to understand when IsValid / IsValidLowLevel should be used. What’s the design purposes and main differences between them? Looks like documentation doesn’t cover this question (or may be I don’t look the correct page?)

As I understood: Unreal object has several lifetime phases:

  1. It is created.
  2. It is initialized
  3. It is going to be destroyed.
  4. It is destroyed.

An we can use it only when it is initialized and not going to be destroyed. So that is the purpose of IsValid.

The question 1: may I propose that object is initialized (and valid) after it’s C++ constructor finished?

The question 2: what are the best practices for validity checking?

  1. If UObject A stores strong reference to an UObject B (stored as UPROPERTY member) and B is never destroyed before A destructor, can I rely only on checking B against nullptr inside methods of A? For example, A is an only owner of B.
  2. If A stores strong reference to an UObject B, but B can be destroyed before A destructor, does this require IsValid call before usage of B inside methods of A?
  3. If A gets object B as UPROPERTY of some another class (for example, GameStateBase subclass), does programmer have to use IsValid function and checking of B against nullptr is not correct because of B lifetime contract is not defined?

The question 3: what is the difference between IsValid, IsValidLowLevel, IsValidLowLevelFast, which one should be used?

Thanks in advance.

Hope, this question will help more newbies as me.

It`s been a while, but I think this should be answered for posterity sake.

IsValid() performs two checks: it checks if the pointer is null and if the UObject is not marked as PendingKill (flagged to be garbage collected). In normal situations you can have a a pointer to pending kill object if you somewhere in your call stack someone calls Destroy() on an Actor that is then passed as a parameter to another function or stored in a local variable, for example.

IsValidLowLevel() checks if an address points to a valid UObject. As the “low level” moniker indicates, it’s to be used in situations that are dealing with low level memory manipulation of UObjects which don’t adhere to the UE4 reflection system.

IsValidLowLevelFast() is a faster version of IsValidLowLevel() that is less accurate (according to it’s description).

Hi, Manoel!

Thanks a lot for the response.

Looks like:

  1. IsValidLowLevel and IsValidLowLevelFast are not designed to be used in an usual C++ development (like storing objects in UPROPERTY data members and checking for “validity”)
  2. IsValid should be a preferred way for checking object “validity” unless there is a contract that variable whether nullptr or valid and you are a super-aware of performance.