ue4 弱指针_智能指针如何实现自动释放

ue4 弱指针_智能指针如何实现自动释放原创文章,转载请注明出处。UE4也有一套智能指针库,整理了一下做个介绍。也请大家做补充。共享指针/共享引用/弱指针/注意事项一.TSharePtr1.如何创建一个TSharePtr2.TSharePtr如何进行类型转换1)TSharePtr转TSharePtr2)ConstTSharePtr转TSharePtr3)TSharePtr转TShareRef3.使用注意事项1)TSharePtr2)类型转换二.TShareRef1.如何创建一个TShareRef2.TShareRef如何进行类型转换1)TS

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

原创文章,转载请注明出处。

UE4也有一套智能指针库,整理了一下做个介绍。也请大家做补充。

文章里面的代码下载链接:智能指针测试代码

一.TSharePtr

1.如何创建一个TSharePtr

/* 智能指针如何使用 */		
void MySharePtrTest();
TSharedPtr<ClassBase> m_pSharePtrBase;	///h中声明的
//智能指针如何使用
void AMyActor::MySharePtrTest()
{ 
   
	m_pSharePtrBase = MakeShareable(new ClassBase());
	
	指针是否为空, 如果为空的话,会执行断言check,导致程序直接崩溃
	if (m_pSharePtrBase.IsValid() || m_pSharePtrBase.Get())
	{ 
   
		//使用nBase
		m_pSharePtrBase->nBase;
	}
}

2.TSharePtr如何进行类型转换

先定义两个类,代码如下

class ClassBase
{ 
   
public:
	int32 nBase;
};

class ClassTop : public ClassBase
{ 
   
public:
	void MyFunc();
};

1)TSharePtr转TSharePtr

StaticCastSharedPtr 介绍

//SharePtr类型转换成其他的SharePtr
void MySharePtrTestCastToAnotherSharePtr();
//SharePtr类型转换成其他的SharePtr
void AMyActor::MySharePtrTestCastToAnotherSharePtr()
{ 
   
	//基类对象指向了派生类的成员.多态案例在这也是一样的
	TSharedPtr<ClassBase> ptrbase = MakeShareable(new ClassTop());
	TSharedPtr<ClassTop> ptrcast = StaticCastSharedPtr<ClassTop>(ptrbase);
	if (ptrcast.IsValid())
	{ 
   
		ptrcast->MyFunc();
	}
}

2)Const TSharePtr转TSharePtr

ConstCastSharedPtr 介绍

//Const SharePtr转换成其他的SharePtr
void MyConstSharePtrTestCastToAnotherSharePtr();
//Const SharePtr转换成其他的SharePtr
void AMyActor::MyConstSharePtrTestCastToAnotherSharePtr()
{ 
   
	//基类对象指向了派生类的成员.多态案例在这也是一样的
	const TSharedPtr<ClassBase> ptrbase = MakeShareable(new ClassTop());

	{ 
   
		//错误写法, 不能通过ConstCastSharedPtr直接转成派生类.
		//TSharedPtr<ClassTop> ptrcast = ConstCastSharedPtr<ClassTop>(ptrbase);
	}
	{ 
   
		//正确写法1
		//先通过ConstCastSharedPtr转成非const的基类
		TSharedPtr<ClassBase> ptrcast = ConstCastSharedPtr<ClassBase>(ptrbase);
		//再通过StaticCastSharedPtr转换
		TSharedPtr<ClassTop> ptrcast2 = StaticCastSharedPtr<ClassTop>(ptrcast);
		if (ptrcast2.IsValid())
		{ 
   
			ptrcast2->MyFunc();
		}
	}

	{ 
   
		//正确写法2
		//直接通过StaticCastSharedPtr转换
		TSharedPtr<ClassTop> ptrcast = StaticCastSharedPtr<ClassTop>(ptrbase);
		if (ptrcast.IsValid())
		{ 
   
			ptrcast->MyFunc();
		}
	}
}

3)TSharePtr转TShareRef

ToSharedRef介绍

//SharePtr类型转换成ShareRef类型
void MySharePtrToShareRef();
//SharePtr类型转换成ShareRef类型
void AMyActor::MySharePtrToShareRef()
{ 
   
	TSharedPtr<ClassBase> ptr = MakeShareable<ClassBase>(new ClassTop());
	if (ptr.IsValid())
	{ 
   
		TSharedRef<ClassBase> ref = ptr.ToSharedRef();
	}
}

3.使用注意事项

1)TSharePtr

1>智能指针可以在.h中定义, 并且可以=nullptr


ShareRef不允许在.h中定义的, 并且一直有值,在二中介绍


2>注意使用前要判断.IsValid()注意是. 不是箭头


3>或者使用.Get进行判断

如果都有值的话再去调用重载的操作符->去获取值, 比较安全。因为使用->的时候会先判断智能指针是否有效, 如果无效的话,直接会导致断言(check),随后程序崩溃。下面贴一下重载的->源码 4>和C++11的shareptr一样,内部都是基于引用计数的。所以你可以通过GetSharedReferenceCount()获取到当前的引用计数 “`cpp FORCEINLINE ObjectType* operator->() const { check( IsValid() ); //可以看到这里的check return Object; } “` ### 2)类型转换
1>ConstCastSharedPtr注意事项

下面是错误写法, 不能通过ConstCastSharedPtr直接转成派生类

TSharedPtr<ClassTop> ptrcast = ConstCastSharedPtr<ClassTop>(ptrbase);

2>通过TSharedPtr中的ToSharedRef()方法可以将TSharePtr转换为TShareRef

二.TShareRef

1.如何创建一个TShareRef

//SharePtr如何使用
void MyShareRefTest();
//SharePtr如何使用
void AMyActor::MyShareRefTest()
{ 
   
	//TSharedRef没有IsValid方法, 因为它一直是有效的
	TSharedRef<ClassBase> ref = MakeShareable(new ClassTop());
	ref->nBase;
}

2.TShareRef如何进行类型转换

1)TShareRef转TShareRef

StaticCastSharedRef 介绍

//ShareRef类型转换成其他的ShareRef
void AMyActor::MyShareRefTestCastToAnotherShareRef()
{ 
   
	//TSharedRef没有IsValid方法, 因为它一直是有效的
	TSharedRef<ClassBase> ref = MakeShareable(new ClassTop());
	TSharedRef<ClassTop> refCast = StaticCastSharedRef<ClassTop>(ref);
	refCast->MyFunc();
}

2)Const TShareRef转TShareRef

ConstCastSharedRef 介绍

//Const ShareRef转换成其他的ShareRef
void AMyActor::MyConstShareRefTestCastToAnotherShareRef()
{ 
   
	//TSharedRef没有IsValid方法, 因为它一直是有效的
	const TSharedRef<ClassBase> ref = MakeShareable(new ClassTop());

	{ 
   
		//错误写法, 不能通过ConstCastSharedRef直接转成派生类.
		//TSharedRef<ClassTop> refcast1 = ConstCastSharedRef<ClassTop>(ref);
	}
	{ 
   
		//正确写法1, 先通过ConstCastSharedRef转换城非Const的基类
		TSharedRef<ClassBase> refcast1 = ConstCastSharedRef<ClassBase>(ref);
		//再通过StaticCastSharedRef转换
		TSharedRef<ClassTop> refcast2 = StaticCastSharedRef<ClassTop>(refcast1);
		refcast2->MyFunc();
	}

	{ 
   
		//正确写法2
		//直接通过StaticCastSharedRef转换
		TSharedPtr<ClassTop> refcast = StaticCastSharedRef<ClassTop>(ref);
		if (refcast.IsValid())
		{ 
   
			refcast->MyFunc();
		}
	}
}

3)TShareRef转TSharePtr

直接赋值即可完成转换动作

//ShareRef类型转换成SharePtr类型
void MyShareRefToSharePtr();
//ShareRef类型转换成SharePtr类型
void AMyActor::MyShareRefToSharePtr()
{ 
   
	TSharedRef<ClassBase> ref = MakeShareable(new ClassTop());
	TSharedPtr<ClassBase> ptr = ref;
}

3.使用注意事项

1)TShareRef

1>ShareRef不允许在.h中定义的, 我这弄了个为什么不允许在.h中的案例,会崩溃,截图

在这里插入图片描述
在这里插入图片描述

2>不能=nullptr这么写

3>使用时候直接用->即可,因为一直有有效值。

2)类型转换

1>ConstCastSharedRef注意事项

下面是错误写法, 不能通过ConstCastSharedRef直接转成派生类

TSharedRef<ClassTop> refcast1 = ConstCastSharedRef<ClassTop>(ref);

2>将TSharedRef转换成TSharedPtr,直接赋值即可

三.TWeakPtr

TWeakPtr有两个奇妙之处
1>他是保持对一个对象的弱引用,不会阻止对象(TWeakPtr)的销毁。如果TWeakPtr销毁了,那么这个弱指针(TWeakPtr)也会为null。也就是不需要我们二次维护了。
2>打破TSharedPtr共享指针带来的循环引用问题

1.如何创建一个TWeakPtr

TWeakPtr的创建必须基于一个TSharedPtr或者TSharedRef

1)通过TSharedPtr初始化一个TWeakPtr

//TWeakPtr如何使用
void MyWeakPtrTest();
//TWeakPtr如何使用
void AMyActor::MyWeakPtrTest()
{ 
   
	TSharedPtr<ClassBase> ptr = MakeShareable(new ClassTop());
	//通过SharePtr初始化TWeakPtr
	TWeakPtr<ClassBase> WeakPtr = ptr;
	TWeakPtr<ClassBase> WeakPtr2(ptr);

	//通过ShareRef初始化TWeakPtr
	TSharedRef<ClassBase> ref = ptr.ToSharedRef();
	TWeakPtr<ClassBase> WeakPtr3 = ref;
	TWeakPtr<ClassBase> WeakPtr4(ref);
}

2)通过TSharedRef初始化一个TWeakPtr

//通过ShareRef初始化TWeakPtr
TSharedPtr<ClassBase> ptr = MakeShareable(new ClassTop());
TSharedRef<ClassBase> ref = ptr.ToSharedRef();
TWeakPtr<ClassBase> WeakPtr3 = ref;
TWeakPtr<ClassBase> WeakPtr4(ref);

2.TWeakPtr的类型转换

TWeakPtr中的.Pin()函数可以将WeakPtr转成TSharedPtr

1)TWeakPtr转TSharePtr

//TWeakPtr如何转换成SharePtr
void MyWeakPtrToSharePtr();
//TWeakPtr如何转换成SharePtr
void AMyActor::MyWeakPtrToSharePtr()
{ 
   
	TSharedPtr<ClassBase> ptr = MakeShareable(new ClassTop());
	//通过SharePtr初始化TWeakPtr
	TWeakPtr<ClassBase> WeakPtr = ptr;

	//利用WeakPtr的.Pin()函数将WeakPtr转成SharedPtr
	TSharedPtr<ClassBase> WeakPtrToSharePtrObj = WeakPtr.Pin();
	if (WeakPtrToSharePtrObj.IsValid())
	{ 
   
		//tdo smth...
	}
}

2)TWeakPtr转TShareRef

其实就是先将WeakPtr转成SharedPtr,再将SharedPtr转SharedRef

//TWeakPtr如何转换成ShareRef
void MyWeakPtrToShareRef();

//TWeakPtr如何转换成ShareRef
void AMyActor::MyWeakPtrToShareRef()
{ 
   
	TSharedPtr<ClassBase> ptr = MakeShareable(new ClassTop());
	//通过SharePtr初始化TWeakPtr
	TWeakPtr<ClassBase> WeakPtr = ptr;

	//利用WeakPtr的.Pin()函数将WeakPtr转成SharedPtr
	TSharedPtr<ClassBase> WeakPtrToSharePtrObj = WeakPtr.Pin();
	if (WeakPtrToSharePtrObj.IsValid())
	{ 
   
		//利用TSharedPtr的ToSharedRef()函数将TSharedPtr转换成TSharedRef
		TSharedRef<ClassBase> ref = WeakPtrToSharePtrObj.ToSharedRef();
	}
}

3.使用注意事项

1>TWeakPtr一定是从TSharedPtr或者TSharedRef过来的

四.TSharedFromThis

将自己的F类继承自TSharedFromThis之后,那么这个类就会知道自己是属于哪一个共享指针。这样说可能有点绕。

1.如何使用TSharedFromThis

代码如何书写如下, 可以看到我继承了: public TSharedFromThis 。继承了这个类其实里面会多一个WeakPtr,存了一个弱引用对象,或者可以叫或引用关系。
在这里插入图片描述

class ClassBase : public TSharedFromThis<ClassBase>
{ 
   
public:
	int32 nBase;
};

class ClassTop : public ClassBase
{ 
   
public:
	void MyFunc() { 
   }
};

有了这个,我们可以直接new出来的原生类上就有了AsShared方法,会存着一个这个类的共享引用。
方便我们直接做转换。比如如下代码

AsShared使用案例

//如何使用继承自TSharedFromThis的类
void MySharedFromThisTest();
//如何使用继承自TSharedFromThis的类
void AMyActor::MySharedFromThisTest()
{ 
   
	TSharedPtr<ClassTop> ptr = MakeShareable(new ClassTop());
	if (ptr.IsValid())
	{ 
   
		//我们通过.Get()将TSharedPtr转换成C++ 原生指针
		ClassTop* pOriginPtr = ptr.Get();

		//现在我们想将pOriginPtr这个原生C++指针怎么转回智能指针呢?
		{ 
   
			//错误的用法, 也能这么用, 但是不建议
			//TSharedPtr<ClassTop> ptr = MakeShareable(pOriginPtr);

			//错误的用法, AsShared()不能用派生类接
			//TSharedPtr<ClassTop> ptr22 = pOriginPtr->AsShared();
		}
		{ 
   
			//正确的用法, AsShared()不能用基类接(基类指的是你继承自TSharedFromThis的那个类)
			TSharedPtr<ClassBase> ptr2 = pOriginPtr->AsShared();
			TSharedPtr<ClassTop> ptr3 = StaticCastSharedPtr<ClassTop>(ptr2);
			if (ptr3.IsValid())
			{ 
   
				ptr3->MyFunc();
			}
		}
	}
}

2.TSharedFromThis哪些场合适合使用?

1>比如我们要写一个单例管理类,可以将数据类上继承自这个
2>有转换成原生类的需求,又想在某一处将原生C++类再次转换成TSharedPtr的需求

3.使用注意事项

1>错误的用法, 也能这么用, 但是不建议

TSharedPtr<ClassTop> ptr = MakeShareable(pOriginPtr);

2>错误的用法, AsShared()不能用派生类接

TSharedPtr<ClassTop> ptr22 = pOriginPtr->AsShared();

3>正确的用法, AsShared()不能用基类接(基类指的是你继承自TSharedFromThis的那个类)

TSharedPtr<ClassBase> ptr2 = pOriginPtr->AsShared();
TSharedPtr<ClassTop> ptr3 = StaticCastSharedPtr<ClassTop>(ptr2);
if (ptr3.IsValid())
{ 
   
	ptr3->MyFunc();
}

五.注意事项总结

1>切记TSharedPtr/TSharedRef/TWeakPtr/TSharedFromThis都是不允许和UObject类一起混合使用的
2>切记不能用UPROPERTY这些反射修饰符来修饰这些智能指针变量
3>切记TSharedRef变量是不允许定义在头文件里面作为成员变量出现的
4>以下四个C++的原生cast方法不适用于这里

不能用于UE4智能指针的转换, 请使用
ConstCastSharedRef/ConstCastSharedPtr/StaticCastSharedPtr/StaticCastSharedRef
static_cast 
dynamic_cast
const_cast
reinterpret_cast

5>在UE4里面还是使用UE4的智能指针,就别用C++11的了,因为UE的智能指针能和UE的代码比如一些容器能够方便的使用。
6>UE的智能指针要比C++占得字节要大
7>这些智能指针都是支持线程安全的,有Fast和Safe两种模式。默认是Fast,也就是非线程安全。
需要标记成Safe模式。回头我想再出一篇关于 UE4线程的内容 构思好把链接放这。
8>TSharedFromThis本身是8字节。因为内置还有一个TWeakPtr,
额外有一个16字节的引用控制器,TWeakPtr用起来比其他俩要慢。因为多了16字节。

该部分的官方详细链接

谢谢大家。有问题请指正。
创作不易,大侠请留步… 动起可爱的双手,来个赞再走呗 <( ̄︶ ̄)>

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/185871.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 大数据应用的几个典型例子「建议收藏」

    大数据应用的几个典型例子「建议收藏」时至今日互联网每天新增的数据量达2.5*10^18字节,而全球90%的数据都是在过去的两年间创造出来的。举个直观的例子来说明一下互联网的数据量:假设大西洋里每一升海水代表一个字节的数据,那么整个大西洋存储的数据也只能到2010年就满了。从外行的角度看来大数据是个挺了不起的东西,它也确实了不起,不过有一个前提就是我们能够有效地处理数据。怎样从海量数据中找出有用的信息才是最重要的。

  • setfacl 命令[通俗易懂]

    setfacl 命令[通俗易懂]setfacl命令是用来在命令行里设置ACL(访问控制列表)。在命令行里,一系列的命令跟随以一系列的文件名。选项-b,–remove-all:删除所有扩展的acl规则,基本的acl规则(所有者,群组,其他)将被保留。-k,–remove-default:删除缺省的acl规则。如果没有缺省规则,将不提示。-n,–no-mask:不要重新计算有效权限。setfacl…

  • java StringTokenizer

    java StringTokenizerStringTokenizer是一个用来分隔String的应用类,相当于VB的split函数。1.构造函数publicStringTokenizer(Stringstr)publicStringTokenizer(Stringstr,Stringdelim)publicStringTokenizer(Stringstr,Stringdelim,boolean

  • 几个关于silverlight的网站[通俗易懂]

    几个关于silverlight的网站[通俗易懂]1.  示例     http://silverlightnuggets.com/ 2. Silverlight示例    http://silverlight.net/community/communitygallery.aspx 3. http://silverlight.net/Learn/ 

    2022年10月19日
  • 未分配的磁盘怎么还原回去_硬盘突然未初始化

    未分配的磁盘怎么还原回去_硬盘突然未初始化大家是否遇到过此类问题,当将外部硬盘插入计算机并找到提示该驱动器已成功安装但没有出现在“此PC”上的通知?当进入Window的磁盘管理实用程序,发现磁盘是未知的,未初始化的,未分配的,那么如何修复未初始化的磁盘?还有丢失数据之后怎么找回?”第1部分:初始化磁盘意味着什么?初始化存储设备(非常类似于格式化过程)是一种擦除驱动器上的数据并允许其在以前不使用时可以再次使用的方法。要进行初始化,可以通过将…

  • 验证码 verifycode 留存可用

    验证码 verifycode 留存可用验证码verifycode留存可用

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号