U++智能指针分为四类:

        共享指针(TSharedPtr)、共享引用(TSharedRef)、弱指针(TWeakPtr(TSharedRef))、唯一指针(TUniquePtr)

        关于智能指针的理解:

        虚幻引擎的共享指针不用于指向UObject,UObject管理有专属的垃圾回收机制。智能指针中,共享指针主要是用来延长对象的生命周期,让其在有被引用的时候存在,不被引用的时候就销毁,可为空;共享引用类比共享指针,但是不可为空,共享引用可以隐式转换为共享指针,共享指针需要调用ToShareRef()函数转换为共享引用,共享指针转换为共享引用时要注意非空判定弱指针是一个观察者,可以将共享指针转化为弱指针,不会改变指向对象的生命周期,因此弱指针引用的对象在使用时也可能被销毁,需要用Pin()转换为共享指针才能访问对象,同时,弱指针也用于打破共享指针的循环引用;唯一指针则主要用于控制指向对象的唯一所有权,只允许该唯一指针访问,指针超出作用域会自动删除对象,不应该与共享指针或共享引用混用。


一、共享指针和共享引用

        初始化:

	struct Struct1
	{
		int32 a = 1;
	};
    TSharedPtr<Struct1> SharedPtr0;//可以创建一个空白的共享指针。
    TSharedPtr<Struct1> SharedPtr1(new Struct1());
    TSharedRef<Struct1> SharedRef1(new Struct1());
    TSharedPtr<Struct1> SharedPtr2 = MakeShared<Struct1>();
    TSharedRef<Struct1> SharedRef2 = MakeShared<Struct1>();

        重置:

        共享指针可以通过Reset()或赋值nullptr来重置,此时如果没有别的共享指针指向原对象则会直接销毁原对象。

SharedPtr1.Reset();
SharedPtr = nullptr;

        共享引用不支持该方法,共享引用设计为始终引用一个有效且非空的对象。

        转移(原指针指向nullptr,浅拷贝(复制)的话就直接=):

SharedPtr2 = MoveTemp(SharedPtr1);//包含静态断言,强制在非常量左值上执行
SharedPtr2 = MoveTempIfPossible(SharedPtr1);

        转换:
 

	TSharedPtr<Struct1> SharedPtr2 = MakeShared<Struct1>();//MakeShared返回的是TSharedRef
    if(SharedPtr1.IsValid())
    {
        SharedRef1 = SharedPtr1.ToShareRef();
    }

        对比、解引用、访问操作都和C++风格的智能指针一样,

        共享指针或引用在构造时可输入lamda函数作为自定义删除器

void DestroyMyObjectType(FMyObjectType* ObjectAboutToBeDeleted)
	{
		// 此处添加删除代码。
	}
	// 这些函数使用自定义删除器创建指南指针。
	TSharedRef<FMyObjectType> NewReference(new FMyObjectType(), [](FMyObjectType* Obj){ DestroyMyObjectType(Obj); });
 
	TSharedPtr<FMyObjectType> NewPointer(new FMyObjectType(), [](FMyObjectType* Obj){ DestroyMyObjectType(Obj); });

二、弱指针

        初始化:

	TWeakPtr<Struct1> WeakPtr1(SharedPtr1);

        复制和重置操作和共享指针相同,不必在意是否为空,使用完也可以进行重置。

        访问:

if(WeakPtr.IsValid())
{
    WeakPtr1.Pin()->a;//转化为共享指针后可进行访问操作
    WeakPtr1.Pin().Get()->a;//Get()返回Struct1*裸指针
}

        打破引用循环(引用虚幻引擎官方文档):

        两个或多个对象使用智能指针保持彼此间的强引用时,将出现引用循环。在此类情况下,对象间会相互保护以免被删除。各对象固定被另一对象引用,因此对象无法在另一对象存在时被删除。如外部对象未对引用循环中对象进行引用,其实际上将出现泄漏。弱指针不会保留自身引用的对象,因此其可中断此类引用循环。要在未拥有对象时对其进行引用,并延长其寿命时,可使用软指针。

        使用警告:

        弱指针不应该用作Set或Map里的键,随时可能无效,IsValid()无法保证持续有效,应当使用Pin()访问。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐