In this lesson, you will learn how to manage the lifecycle of non-UObject resources that require multiple owners using the TSharedPtr smart pointer.
Beyond the Garbage Collector
While UObject instances are managed by Unreal’s built-in Garbage Collector, your project will frequently use standard C++ classes (non-UObject types) to handle data structures, complex algorithms, or heavy logic. Because these objects aren't tracked by the GC, you are responsible for their memory.
TUniquePtr is great for sole ownership, but what happens when several systems need to access the same resource simultaneously? You don't want the object to be deleted while one system is still using it. This is where TSharedPtr comes in.
How TSharedPtr Works
A TSharedPtr maintains an internal reference count. Every time you copy the pointer (e.g., passing it to another class), the reference count increases. When a TSharedPtr goes out of scope or is reset, the count decreases. Once the count reaches exactly zero, the object is automatically deleted from memory.
Consider this example:
// Create a shared pointer to a custom non-UObject class
TSharedPtr<FMyCustomData> DataPtr = MakeShared<FMyCustomData>();
// Pass it to another manager; the reference count is now 2
ManagerA->SetData(DataPtr);
ManagerB->SetData(DataPtr);
// Even if we reset our local pointer, the object persists
DataPtr.Reset();
Safety and Usage
Using TSharedPtr prevents memory leaks and dangling pointers by ensuring that the underlying memory is only freed when the very last owner releases it.
Important: Never use TSharedPtr to manage UObjects. Because UObjects are handled by the Garbage Collector, using TSharedPtr on them will bypass the reflection system and cause critical crashes. Use TSharedPtr exclusively for plain C++ classes or structs that exist outside the UObject system.
Key Takeaway: TSharedPtr provides automated, reference-counted memory management for non-UObject resources, ensuring an object is safely destroyed only when all its owners have relinquished their hold.