UE4的Smart Pointer(智能指针)
UE4智能指针注意事项
- 由于
UObject
类型自带垃圾回收,所以UE4智能指针所指向的对象的类型不能是UObject
。 - 避免将
TSharedRef
或TSharedPtr
作为函数参数进行传递,此操作将因取消引用和引用计数而产生开销。建议将引用对象作为const&
进行传递。 - 以下为UE4智能指针的解除引用操作示例:
ptr->values;
ptr.Get()->values;
(*ptr).values;
UE4智能指针优点
- 所有UE4支持的平台都能使用UE4的智能指针。
- 与其他UE4容器或类型进行无缝的协作。
- 拥有对线程安全功能的支持。线程安全的版本是无锁的。
- 比C++标准库提供的智能指针更快。其时间复杂度为常量。
- 比C++标准库提供的智能指针更节省内存。UE4共享指针在64位下仅为C++指针大小的两倍(加上共享的16字节引用控制器)。唯一指针的大小与C++的指针大小相同。
唯一指针
在UE4里,唯一指针为TUniquePtr
。
唯一指针仅会显式拥有其引用的对象。仅有一个唯一指针指向给定资源,因此唯一指针可转移所有权,但无法共享。复制唯一指针的任何尝试都将导致编译错误。唯一指针超出有效范围时,其将自动删除其所引用的对象。
若需要多个智能指针指向同一块资源,则可以使用共享指针。
TUniquePtr的使用
TUniquePtr::IsValid
方法可以检查指针的有效性。TUniquePtr::Get
方法获取指针,不具有有效性检测功能。TUniquePtr::Release
方法释放指针所指向的资源。TUniquePtr::Reset
方法使指针引用新的资源,并销毁之前引用的资源。- 函数
MakeUnique<T>()
可分配资源并创建唯一指针,但要求传递公有构造函数的参数。
共享指针
在UE4里,共享指针为TSharedPtr
。
TSharedPtr<>
是跟据拷贝构造函数进行引用计数的智能指针。
TSharedPtr的使用
TSharedPtr::IsValid
方法可以检查指针的有效性。TSharedPtr::Get
方法获取指针,同时具有有效性检测功能。TSharedPtr::Reset
方法可以释放指针计数。TSharedPtr::IsUnique
方法可以检查该共享指针是否为指向所引用的资源的唯一指针。TSharedPtr::GetSharedReferenceCount
方法可以检查一个共享指针的引用数。TSharedPtr::ToSharedRef
方法可以将该共享指针转换为共享引用。- 函数
MakeShareable
可将原生C++指针变成共享指针。效率比MakeShared<T>()
低。 - 函数
MakeShared<T>()
可分配资源并创建共享指针,但要求传递公有构造函数的参数。 - 函数
StaticCastSharedPtr<T>()
可将基类的共享指针转换为派生类的共享指针。 - 函数
ConstCastSharedPtr<T>()
可将const指针转换为非const指针。
共享引用
在UE4里,共享引用为TSharedRef
。
与共享指针的区别是共享指针可以为NULL,而共享引用不能为NULL。
共享引用也拥有MakeSharedRef<T>()
、StaticCastSharedRef<T>()
和ConstCastSharedRef<T>()
函数。
弱指针
在UE4里,弱指针为TWeakPtr
。
弱指针类与共享指针类似,但不拥有其引用的对象,因此不影响其生命周期。弱指针用于防止共享指针循环引用而引起的错误,但也意味着弱指针可能在无预警的情况下为空。弱指针可生成指向其引用对象的共享指针,确保程序员能对该对象进行安全临时访问。
TWeakPtr的使用
TWeakPtr::IsValid
方法可以检查指针的有效性。TWeakPtr::Reset
方法可以重置此弱指针,删除对该对象的弱引用。如果没有其他对该对象的共享或弱引用,则跟踪对象将被销毁。TWeakPtr::HasSameObject
方法检查这个弱指针指向的对象与指定的对象指针所指向的对象是否相同。TWeakPtr::Pin
方法将此弱指针转换为可用于访问对象的共享指针(如果它尚未过期)。在尝试取消对共享指针的引用之前,应该对其进行检查以确保返回的指针是有效的。
TSharedFromThis
TSharedFromThis
可以方便的从一个原始指针转为一个共享指针,并且自带一个弱指针。
class cls : public TSharedFromThis<cls>
{
public:
void func() {}
};
TSharedPtr<cls> sptr = MakeShareable(new cls);
sptr.Get()->func(); // 同下
sptr->func(); // 同上
cls* cptr = sptr.Get();
if (cptr)
TSharedPtr<cls> sptr2 = cptr->AsShared();