The **Unreal Smart Pointer Library** is a custom implementation of shared references (**TSharedRef**), shared pointers (**TSharedPtr**), weak pointers (**TWeakPtr**) as well as related helper functions and classes. This implementation is modeled after the C++0x standard library's shared_ptr as well as Boost smart pointers.
* Exceptions were not needed nor desired in our implementation.
* We wanted more control over performance (inlining, memory, use of virtuals, etc.).
* Potentially easier to debug (liberal code comments, etc.).
* Prefer not to introduce new third party dependencies when not needed.
### Helper Classes and Functions
Several helpers in the form of classes and functions are provided in the library to make using smart pointers easier and more intuitive.
| Helper | Description |
| --- | --- |
|[REGION:tablesection]Classes[/REGION]||
| TSharedFromThis | You can derive your own class from this to acquire a TSharedRef from "this." |
|[REGION:tablesection]Functions[/REGION]||
| MakeShareable() | Used to initialize shared pointers from C++ pointers (enables implicit conversion). |
| StaticCastSharedRef() | Static cast utility function, typically used to downcast to a derived type. |
| ConstCastSharedRef() | Converts a 'const' reference to 'mutable' smart reference. |
| DynamicCastSharedRef() | Dynamic cast utility function, typically used to downcast to a derived type. |
| StaticCastSharedPtr() | Static cast utility function, typically used to downcast to a derived type. |
| ConstCastSharedPtr() | Converts a 'const' smart pointer to 'mutable' smart pointer. |
| DynamicCastSharedPtr() | Dynamic cast utility function, typically used to downcast to a derived type. |
## Smart Pointer Implementation Details
The various types of smart pointers implemented in the Unreal Smart Pointer Library all share some general characteristics in terms of performance, memory, etc.
### Performance
Always keep performance in mind when considering using shared pointers. They are generally pretty fast; however, shared pointers are not meant to be used everywhere. They are great for certain high level systems, or tools programming, but not well-suited for low level engine/rendering paths.
Some of the general performance benefits of shared pointers are:
* All operations are constant time.
* Shared pointer deference is just as fast as C++ pointer.
* Copying shared pointers never allocates memory.
* Thread-safe versions are lock-free.
* Fast implementation compared to Boost or STL.
Performance drawbacks of shared pointers include:
* Overhead to creating and copying pointers.
* Reference count housekeeping.
* Shared pointers use more memory than C++ pointers.
* Extra heap allocation for reference controller.
* One for each unique object referenced by any number of shared pointers.
* Weak pointer access is a bit slower than shared pointer access.
The Reference controller object is 12 bytes (when compiling for 32-bit) consisting of:
* C++ pointer (uint32)
* Shared reference count (uint32)
* Weak reference count (uint32)
[REGION:note]
Only one reference controller is created per object, no matter how many shared/weak pointers refer to an object.
[/REGION]
### Reflection
Shared pointers are non-intrusive which means the class itself does not know whether it is owned by a shared pointer (or reference). In general, this is okay, but sometimes you really want to access the current instance as a shared reference. The solution to this is to derive the class from `TSharedFromThis<>`.
By deriving from TSharedFromThis<>, you can use the **AsSharedRef()** method to convert 'this' to a shared reference. This can be very useful with class factories that always return shared references.
class FAnimation : public TSharedFromThis<FMyClass>
{
void Register()
{
// Access a shared reference to 'this'
TSharedRef<FMyClass> SharedThis = AsSharedRef();
// Class a function that is expecting a shared reference
AnimationSystem::RegisterAnimation( SharedThis );
}
}
### Casting
You can cast shared pointers (and references) easily. Up-casting is implicit, just like with C++ pointers.
Cast away const (evil, but sometimes necessary):
ConstCastSharedPtr<T>( ... )
Static cast (often used to downcast to derived class pointers):
StaticCastSharedPtr<T>( ... )
[REGION:note]
Dynamic cast is not supported (no RTTI.) Instead, you should use the static cast above.
[/REGION]
### Thread Safety
Regular shared pointers are only safe to access on a single thread. If you need multiple threads to have access, use the thread-safe versions of pointer classes:
* `TThreadSafeSharedPtr<T>`
* `TThreadSafeSharedRef<T>`
* `TThreadSafeWeakPtr<T>`
* `TThreadSafeSharedFromThis<>`
These versions are a bit slower due to atomic reference counting, and behavior is mostly consistent with regular C++ pointers:
* Reads and copies are always thread-safe.
* Writes/resets must be synchronized to be safe.
[REGION:warning]
If you know your pointer will never be accessed by more than one thread, do not use the thread safe version.
The SharedPointerTesting.h file (located in [UE4RootLocation]/Engine/Source/Runtime/Core/Public/Templates/) contains various examples of using shared pointers and references.