It is said that “Unreal walks all the UPROPERTY pointer” to execute garbage collection. Are there any impacts of declaring a raw pointer that points to a UObject without a UPROPERTY() macro then? Should I always declare raw pointers (to UObject) with a UPROPERTY() macro even without metadata?
Yes, if you are storing a raw UObject*
(by UObject I mean anything derived from it) then if that were to be garbage collected that pointer won’t be nulled and continue to point at that now invalid memory.
If you don’t want to be the thing keeping something from being garbage collected you should use TWeakObjectPtr
instead of a raw pointer as this will be nulled when the object gets garbage collected.
FHitResult
for example stores the HitActor as a TWeakObjectPtr<AActor>
Hey, thanks for the fast response!
That makes sense. What about the TObjectPtr<> from Unreal Engine 5? Does it act like a TWeakObjectPtr or it’s still better to use TWeakObjectPtr over TObjectPtr? I’m sorry if it’s confusing, but all these pointers are kind hard to understand with all the details.
Moreover, looking back a code I wrote, what about a raw pointer inside a non-UObject class? If I use a raw pointer to the non-UObject instance (I know I should’ve used a TSharedPtr now), and I use “delete” on the non-UObject instance, will the raw pointer inside it be nulled?
To be honest, not 100% versed in the purpose of that is. All I know is that it’s entirely for development purposes and in a shipping build TObjectPtr<T>
is exactly the same as T*
. i.e. its definition would be something like
#if UE_BUILD_SHIPPING
template<class T>
using TObjectPtr = T*;
#else
template<class T>
using TObjectPtr = /* actual implementation */;
#endif
From a quick search it seems to mostly about catching uses of uninitialised pointers.
TSharedPtr
is Unreal’s version of std::shared_ptr
, it’s for when you need shared ownership of a resource which isn’t a typical use case
https://www.learncpp.com/cpp-tutorial/stdshared_ptr/
Generally when you do need dynamic allocation you have a unique owner of that and in which case you should use TUniquePtr
/std::unique_ptr
. Non-owning raw pointers are fine.
No, C++ won’t automatically null your pointer; with that said after you delete
it why would you then try to use it in any way afterwards?
Hmmm, that makes sense. I’ll dig more into that.
Got it, I will revise these pointers more carefully.
Yup, I indeed though it would not automatically null the pointer. I was just guessing for correctness-sake. Like deleting a object and be not careful enough to eventually use it somehow.
Anyway, thanks for the discussion. I’ve been always using either raw pointers or raw pointeirs with UPROPERTY() when it had some kind o metadata in it - or when Unreal’s API forced me to use some of its other types. I will dig more into the different types of pointers there are and use them more properly.
However, can you tell me if this sound correct:
If pointing to a UObject: Use raw pointer always with UPROPERTY() or TWeakObjectPtr.
If pointing to a non-UObject: Either use TSharedPtr or TUniquePtr depending on desired ownership.
Sounds good to me.