实现原理
智能指针的实现原理一个是引用计数,一个是利用超出作用域自动析构原理。
当引用计数为0时,释放内存。
TWeakPtr
实现细节
UE很巧妙的撸了个 WeakObjectPtr ,实现原理很简单,它的核心就两个参数:
//WeakObjectPtr.h
int32 ObjectIndex;
int32 ObjectSerialNumber;
//WeakObjectPtr.cpp
ObjectIndex = GUObjectArray.ObjectToIndex((UObjectBase*)Object);
ObjectSerialNumber = GUObjectArray.AllocateSerialNumber(ObjectIndex);
ObjectIndex 就是当前WeakObjectPtr 指向的对象在数组GUObjectArray内的索引,而ObjectSerialNumber 则是该对象当初在创建的时候的唯一序列码 SerialNumber (赋值和自增都是原子操作,线程安全);因为它不直接引用 Obj 指针 ,因此不会影响 GC,然后 ObjectSerialNumber 会跟 GUObjectArray 内 ObjectIndex 位置对象的 SerialNumber 对比,不一样就表示根本不是同一个对象
应用细节
避免crash
对于一些会隔帧执行的代码(定时器回调、 委托等),如果有用到 UObject 对象,强烈建议使用 WeakObjectPtr,能减少很多隐藏的 Crash,让你的代码更乐百氏( Robust )
循环引用
由于TWeakPtr不参与引用计数,因此可以用来解循环引用问题。循环引用是指对象A中存在B的引用,对象B中存在A的引用。如图所示

图中内存A和内存B各被引用2次,因此引用计数为2。当超出作用域时,指针A和指针B析构,因此引用计数各减1,此时引用计数为1不为0,因此内存A和内存B无法释放,这就是循环引用造成内存泄漏问题。解决方式就是对象A中使用弱指针指向B,对象B中使用弱指针指向A。
TSharedPtr
杂项
TWeakObjectPtr与TWeakPtr的区别是:TWeakObjectPtr用于指向UObject对象,而TWeakPtr用于指向常规C++对象。TWeakObjectPtr可以用来判断对象是否已销毁。
WeakObjectPtr<UActorComponent> ptr = MakeWeakObjectPtr(TestUObj);//弱对象指针
TestUObj->DestroyComponent();//销毁
if (ptr.IsValid())
{
UE_LOG(LogTemp, Log, TEXT("Not Destroy!"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("Destroyed!"));//正常了
}
Comments NOTHING