Best "Shared Pointer" practice for a data object?

I have a UBank that holds data, in the form of TArray< UItem >. This UBank has a Get and Set method to add / remove these UItems. These UItems are created outside of UBank, and then deposited into it. The UBank merely holds the data, and acts as a “single source of truth”. Both UBank and UItem extend off of UObject.

From what I’ve read, I’m lead to believe that UBank should hold these items in the form of TArray< TSharedPtr< UItem > >, since UBank is intended to be their owner. Whereas the Get method should return a TWeakPtr< UItem >, since anyone who needs a reference is merely borrowing that item, and they may need to know when the item has expired.

Assuming the above is correct, I’m really not sure what the Set method should take in as a parameter. Since the parameter will never be null, should it take in a TSharedRef< UItem >?

I’m having a difficult time rationalizing these pointer types, and I’d appreciate any insight you can give regarding this scenario. Did I guess correctly, or am I misunderstanding their intended usage?

Not necessarily. It’s frequently totally legitimate for each user to keep the object alive – e g, even if it’s removed from the bank, it will still be kept alive by the other reference.

That depends on what it is you want to do. It could take an integer, as an index into the TArray for example. If it takes an object reference, then… you already have a reference, why would you need to get it?

Ah, sorry, there was a typo. I meant to type “Set” instead of “Get”. I’m unsure what parameter type the Set method should have, whether SharedRef< UItem > is a reasonable parameter.

But based on your response, I assume I’m overthinking it, and my ultimate plan is probably fine. I want SharedPtr to signify that the object is within its owner, and SharedRef signifying an object that has yet to reach its owner. With WeakPtr being an indication that the owner is elsewere.

Do not mix UObjects and shared pointers stuff.

UObjects have their own mechanisms for memory management via the reflection system.

Shared pointers are meant to be used for everything that is non-UObjects, eg. Slate widgets, JSON objects, and other pure-C++ that you may want to have auto memory management on.

These classes cannot be used with the UObject system because Unreal Objects use a separate memory-tracking system that is better-tuned for game code.

For UObjects, you should use either :

  • Raw object pointer with UPROPERTY marking, which is a hard reference, meaning it will keep the referenced object alive as long as the pointer exists

  • FWeakObjectPtr or TWeakObjectPtr<UItem> without UPROPERTY marking, which is a soft ref so it will not keep the object alive, and has capabilities to properly detect when the referenced object has been destroyed.

  • FSoftObjectPath or FSoftClassPath or their template variants, with or without UPROPERTY, if you want to reference an object by path, eg. an object that may not have been loaded yet. Probably not what you need for your use case.

(note: TObjectPtr<UItem> is the same thing as UItem* and also needs UPROPERTY, however you should probably avoid using TObjectPtr in containers like TArray)


edit: found this post for more info

1 Like

Ah, thanks for the correction! Thank you!

SharedRef<> is fine, and a plain UItem * or TObjectPtr<UItem> would probably also work. The benefit of using the SharedRef<> is that the new SharedRef<> inside the container will share with the argument.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.