Type | 解释 | 内存占用 | 性能 |
---|---|---|---|
TUniquePtr | 专属所有权智能指针,只能转移,不能复制 | 默认和裸指针相同,有状态的删除其和采用函数指针实现的删除器会增加尺寸 | 基本裸指针相同 |
TSharedPtr | 引用计数的非侵入式的权威智能指针 | 默认是裸指针两倍,但是多出了控制块的内存 | 有一定的内存消耗,大约是两倍 |
TSharedRef | 引用计数的非侵入式的权威智能引用(只是不能为null) | 同上 | 同上 |
TWeakPtr | 引用计数的、非侵入式弱指针引用 | 两倍的裸指针大小,有一个指针指向控制块 | 比Tsharedptr略慢 |
- 所有共享指针的内存消耗(8字节)(32位系统)
- 源指针(32位)
- 引用控制器(32位)
- 应用控制器(12字节)
- 源指针
- 共享引用计数
- 弱引用计数使用的方法(以TSharedPtr为例)
//声明一个类
Class MyClass
{
public:
int values;
};
//分配以及初始化
TSharedPtr<MyClass> EmptySharedClass; //这是一个空的共享指针
TSharedPtr<MyClass> FirstSharedObject(new MyClass()); //声明并初始化了一个共享指针
//复制指针:
//当复制了一个共享指针,那引用数就会增加
TSharedPtr<MyClass> anotherObject = FirstSharedObject;
//获取引用计数
FirstSharedObject.GetSharedReferenceCount();
//解引用
FirstSharedObject->values;
FirstSharedObject.Get()->values;
(*FirstSharedObject).values;
//释放当前指针
FirstSharedObject.Reset();
//指针合法性
FirstSharedObject.IsValid()
或者:
FirstSharedObject.Get() != nullptr
- Tshared实现原理
- ObjectType\* Object - 裸指针
- FReferenceControllerBase - 引用计数器
- FReferenceControllerBase是抽象类, 子类需要实现DestroyObject()方法. (目前均使用派生类TReferenceControllerWithDeleter) SharedReferenceCount为共享计数, WeakReferenceCount为弱指针计数. SharedReferenceCount降为0时, 不管WeakReferenceCount的数值, Object被销毁. WeakReferenceCount降为0时, FReferenceControllerBase 被销毁.
##详细内容
TSharedPtr, TSharedRef, TWeakPtr均使用该类计数
FReferenceControllerBase是抽象类, 子类需要实现DestroyObject()方法. (目前均使用派生类TReferenceControllerWithDeleter)
SharedReferenceCount为共享计数, WeakReferenceCount为弱指针计数.
SharedReferenceCount降为 0 时, 不管WeakReferenceCount的数值, Object被销毁.
WeakReferenceCount降为 0 时, FReferenceControllerBase 被销毁.
不可用于UObject, 允许为null, 带引用计数, 生命周期完结自释放的智能指针, 允许拷贝多份, 每份均指向相同的对象.
使用右值构造/赋值时, 传入智能指针会被释放.
有线程安全非线程安全两个版本
每复制一份, 引用计数+1, 每释放一份, 引用计数-1.
不可用于UObject, 不允许为null, 带引用计数, 生命周期完结自释放的智能指针, 允许拷贝多份, 每份均指向相同的对象.
与TSharedRef的区别仅为不允许为null.
TSharedPrt::ToSharedRef()方法用于创建一个共享引用.
仅能通过TSharedPrt或TSharedRef构造的弱指针, 随时会变成空指针, 使用前必须校验是否为空.
与TSharedPrt或TSharedRef使用同一个FReferenceControllerBase.
TWeakPtr无法直接访问对象, 必须通过Pin()方法创建一个TSharedPtr, 通过TSharedPtr访问对象.
弱指针计数不会阻止对象销毁
boost::scoped_ptr
生命周期完结后自释放的智能指针(构造的裸指针必须是new出来的).
拷贝构造/赋值时会new一个新的对象.
手动释放(Release)后, 该智能指针不再负责该对象的销毁.
与TScopedPointer功能一致, 唯一的区别是拷贝构造时不会new.
std::unique_ptr
具有唯一性, 生命周期完结后自释放的智能指针, 不支持拷贝, 只支持移动.
使用右值赋值时, 原指向对象会被销毁.
手动释放(Release)后, 该智能指针不再负责该对象的销毁.
使用ObjectIndex及ObjectSerialNumber指向UObject的弱指针.
提供AsShared方法获取共享指针, 凡是派生自TSharedFromThis的对象请通过AsShared获取智能指针, 可以保证引用计数器的一致.
使用引用计数的允许为空的智能指针, 创建时有三种模式(ESPMode)可选:
NotThreadSafe- 非线程安全
Fast(默认) - FORCE_THREADSAFE_SHAREDPTRS为 1 是等价于ThreadSafe, 反之等价于NotThreadSafe
ThreadSafe - 线程安全, 但是相对昂贵
注: TSharedRef 不允许用于UObjects
template< class ObjectType, ESPMode Mode >
ObjectType* Object - 裸指针
SharedPointerInternals::FSharedReferencer< Mode > SharedReferenceCount - 引用计数器 (详见1.2)
ObjectType& Get() const
获取裸指针, 请慎重存储返回值.
const int32 GetSharedReferenceCount() const
获取当前指针的引用计数
void Reset()
释放引用
TSharedRef< ObjectType, Mode > ToSharedRef() const
创建一个共享引用
const bool IsValid() const
当前指针是否有效
template< ESPMode Mode >
typedef FReferenceControllerOps<Mode> TOps;
FReferenceControllerBase* ReferenceController
引用计数核心, 负责记录引用计数及销毁操作 (详见1.3)
注: FReferenceControllerBase是一个抽象类, 目前TSharedRef使用的ReferenceController是TReferenceControllerWithDeleter
FSharedReferencer& operator=( FSharedReferencer const& InSharedReference )
TOps::AddSharedReference(NewReferenceController);
增加ReferenceController->SharedReferenceCount计数, 线程安全版使用InterlockedIncrement, 非线程安全版直接++
TOps::ReleaseSharedReference(ReferenceController)
减少ReferenceController->SharedReferenceCount计数, 线程安全版使用InterlockedDecrement, 非线程安全版直接--
若ReferenceController->SharedReferenceCount为 0
ReferenceController->DestroyObject()进行销毁
ReleaseWeakReference(ReferenceController)
若WeakReferenceCount为0, delete ReferenceController
FORCEINLINE ~FSharedReferencer()
TOps::ReleaseSharedReference(ReferenceController);
int32 SharedReferenceCount - 共享引用计数, 该计数为 0 时会销毁Object , 即便WeakReferenceCount不为 0
int32 WeakReferenceCount - 弱指针引用计数
FReferenceControllerBase( FReferenceControllerBase const& )
无定义, private, 隐藏左值拷贝构造
FReferenceControllerBase& operator=( FReferenceControllerBase const& )
无定义, private, 隐藏左值赋值
template <typename ObjectType, typename DeleterType>
void* Object - 裸指针
继承自FReferenceControllerBase, 目前是FReferenceControllerBase的派生类
virtual void DestroyObject()
使用DeleterType的operator()方法来释放Object
DeleterType通过DefaultDeleter<ObjectType>()创建
DefaultDeleter通过模板特化实现不同类型的delete, 默认直接使用delete.
SharedPtr( OtherType* InObject )
this->Object( InObject )
this->SharedReferenceCount( SharedPointerInternals::NewDefaultReferenceController( InObject ) )
this->SharedReferenceCount.ReferenceController( NewDefaultReferenceController )
NewDefaultReferenceController = nullptr;
SharedPointerInternals::EnableSharedFromThis( this, InObject, InObject );
TSharedPtr( TSharedPtr const& InSharedPtr )
this->Object( InSharedPtr.Object )
this->SharedReferenceCount( InSharedPtr.SharedReferenceCount )
this->SharedReferenceCount.ReferenceController( InSharedPtr.SharedReferenceCount.ReferenceController )
TOps::AddSharedReference(this->SharedReferenceCount.ReferenceController);
TSharedPtr( TSharedPtr&& InSharedPtr )
this->Object( InSharedPtr.Object )
this->SharedReferenceCount( MoveTemp(InSharedPtr.SharedReferenceCount) )
this->SharedReferenceCount.ReferenceController( InSharedReference.ReferenceController )
InSharedPtr.SharedReferenceCount.ReferenceController = nullptr;
InSharedPtr.Object = nullptr;
TSharedPtr& operator=( TSharedPtr const& InSharedPtr )
this->SharedReferenceCount = InSharedPtr.SharedReferenceCount;
this->SharedReferenceCount.ReferenceController( InSharedPtr.SharedReferenceCount.ReferenceController )
TOps::AddSharedReference(this->SharedReferenceCount.ReferenceController);
this->Object = InSharedPtr.Object;
return *this;
TSharedPtr& operator=( TSharedPtr&& InSharedPtr )
this->Object = InSharedPtr.Object;
InSharedPtr.Object = nullptr;
this->SharedReferenceCount = MoveTemp(InSharedPtr.SharedReferenceCount);
auto OldReferenceController=this->SharedReferenceCount.ReferenceController;
InSharedPtr.SharedReferenceCount.ReferenceController = nullptr;
this->SharedReferenceCount.ReferenceController = NewReferenceController;
TOps::ReleaseSharedReference(OldReferenceController);
return *this;
使用引用计数的不允许为空的智能指针.
相关逻辑与TSharedPtr相同, 仅不允许Object为空.
ObjectType* Object
SharedPointerInternals::FSharedReferencer< Mode > SharedReferenceCount
使用引用计数的智能指针, 弱指针不会阻止对象销毁, 使用过程中会遇到指针突然变空的情况.
TWeakPtr不能通过裸指针构造, 只能通过其他智能指针构造.
ObjectType* Object - 裸指针
SharedPointerInternals::FWeakReferencer< Mode > WeakReferenceCount - 引用计数器
const bool IsValid() const
return Object != nullptr && WeakReferenceCount.IsValid();
如前文所说, 弱指针并不阻止Object销毁, 故TWeakPtr::Object并不能作为是否有效的条件, 需要使用WeakReferenceCount.IsValid()来判断.
void Reset()
释放引用
TSharedPtr< ObjectType, Mode > Pin() const
获取当前弱指针的共享指针, 请务必记得IsValid判断.
弱指针没有Get方法, 也没有重写operator*及operator->, 想要使用弱指针指向的对象, 必须通过Pin方法获取共享指针.
typedef FReferenceControllerOps<Mode> TOps;
FReferenceControllerBase* ReferenceController
FSharedReferencer& operator=( FSharedReferencer const& InSharedReference )
InSharedReference WeakReference + 1
this WeakReference - 1
this = InSharedReference
~FWeakReferencer()
TOps::ReleaseWeakReference(ReferenceController);
WeakReferenceCount为 0 时销毁FReferenceController
仿照boost::scoped_ptr写的指针, 没有引用计数, 生命周期完结时自动delete.
ReferencedType* Reference - 裸指针
TScopedPointer(ReferencedType* InReference = nullptr)
TScopedPointer(const TScopedPointer& InCopy)
拷贝构造时, 使用new创建新的对象, InCopy 与与 this 指向不同的对象指向不同的对象.
~TScopedPointer()
ReferencedType* GetOwnedPointer() const
获取裸指针
ReferencedType* Release()
释放该指针, 并返回裸指针. 调用后TScopedPointer不再负责该指针的销毁.
与TScopedPointer功能一致, 唯一的区是构造时别不会new新的对象.
ReferencedType* Reference - 裸指针
TAutoPtr(ReferencedType* InReference = nullptr)
~TAutoPtr()
仿照std::unique_ptr写的指针, 具有唯一性, 不支持拷贝, 只支持移动.
私有继承自Deleter, 通过static_cast<Deleter&>(*this)执行销毁操作.
T* Ptr - 裸指针
private TUniquePtr(const TUniquePtr&) - 禁止拷贝
private UniquePtr& operator=(const TUniquePtr&) - 禁止拷贝
TUniquePtr(TUniquePtr&& Other)
使用右值构造, 构造后Other的指针被置空.
TUniquePtr& operator=(TUniquePtr&& Other)
使用右值赋值, 赋值后Other的指针被置空, this 原来指向的对象被销毁原来指向的对象被销毁.
~TUniquePtr()
T* Release()
释放该指针, 并返回裸指针. 调用后TUniquePtr不再负责该指针的销毁.
支持指向UObject的弱指针, 本身并不包含裸指针, 通过UObject的Index来指向对象.
int32 ObjectIndex - 指向UObject的ObjectIndex
int32 ObjectSerialNumber - 指向UObject的ObjectSerialNumber
FWeakObjectPtr(const class UObject *Object)
FWeakObjectPtr(const FWeakObjectPtr &Other)
UObject* FWeakObjectPtr::Get(bool bEvenIfPendingKill) const
获取当前指向的UObject
UObject* FWeakObjectPtr::GetEvenIfUnreachable() const
获取当前指向的UObject(RF_PendingKill | RF_Unreachable)
UObject* FWeakObjectPtr::Get() const
获取当前指向的UObject(非RF_PendingKill )
void Reset()
重置ObjectIndex及ObjectSerialNumber
为派生自TSharedFromThis的对象提供AsShared方法, 无论何时调用均可获得相同FReferenceControllerBase的智能指针.
mutable TWeakPtr< ObjectType, Mode > WeakThis - 指向this的弱指针
TSharedRef< ObjectType, Mode > AsShared()
将WeakThis转换成TSharedPtr并返回
void UpdateWeakReferenceInternal( TSharedPtr< SharedPtrType, Mode > const* InSharedPtr, OtherType* InObject ) const
在该对象第一次转化成TSharedPtr或TSharedRef时通过EnableSharedFromThis触发, 创建WeakThis弱指针.
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。