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)
blank

相关推荐

  • log4cpp 使用完全手册「建议收藏」

    log4cpp 使用完全手册「建议收藏」原文链接 点击打开链接一、log4cpp概述     Log4cpp是一个开源的C++类库,它提供了C++程序中使用日志和跟踪调试的功能,它的优点如下:提供应用程序运行上下文,方便跟踪调试;可扩展的、多种方式记录日志,包括命令行、文件、回卷文件、内存、syslog服务器、Win事件日志等;可以动态控制日志记录级别,在效率和功能中进行调整;所有配置可以通过配置文件进行动态调整;多语言支持,包括Ja…

  • Bootstrapper Manifest Generator

    Bootstrapper Manifest GeneratorThistoolisasetoftoolsforworkingwiththePre-requisitebootstrapperinVisualStudiothatisusedbySetupProjectsandClickOnce.Thereareprojectstoenableyoutocreateyourown”packages…

  • Random的nextInt方法[通俗易懂]

    Random的nextInt方法[通俗易懂]Random类中的nextInt()方法(注:不带参数)会随机产生所有有效的整数,包括正数,负数和零。Random类中的nextInt(intn)方法会产生[0,n)之间的随机int值(包含0,不包含n)两种生成介于[0,100)的随机数的方法:方法一:用Random类中的nextInt()方法packagech06;importjava.util.Random;…

  • httprunner(7)测试用例RunRequest

    httprunner(7)测试用例RunRequest测试用例分层每个测试用例都有1个或多个测试步骤(List[step]),每个测试步骤对应一个API请求或其他用例的引用。从上图分析,我们可以看到testsuite中包含了3个测试用例,testca

  • CentOS7打开、关闭端口[通俗易懂]

    CentOS7打开、关闭端口[通俗易懂]CentOS7使用的是firewall防火墙,不再是原来的iptables1:查看firewall防火墙状态firewall-cmd–state或者systemctlstatusfirewalld2:打开防火墙systemctlstartfirewalld3:关闭防火墙systemctlstopfire…

  • Django(64)频率认证源码分析与自定义频率认证[通俗易懂]

    Django(64)频率认证源码分析与自定义频率认证[通俗易懂]前言有时候我们发送手机验证码,会发现1分钟只能发送1次,这是做了频率限制,限制的时间次数,都由开发者自己决定频率认证源码分析defcheck_throttles(self,request):

发表回复

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

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