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

相关推荐

  • STM32的IWDG(独立看门狗)详细用法

    STM32的IWDG(独立看门狗)详细用法文章出处:https://www.cnblogs.com/Liu-Jing/p/7243029.html章参考资料:《STM32F4XX中文参考手册》IWDG章节。1、IWDG简介:  STM32有两个看门狗,一个是独立看门狗另外一个是窗口看门狗,独立看门狗号称宠物狗,窗口看门狗号称警犬,本章我们主要分析独立看门狗的功能框图和它的应用。独立看门狗用通俗一点的话来解释就是一个12位的递减计…

  • anaconda+pycharm的安装与配置教程

    anaconda+pycharm的安装与配置教程注:anaconda是自带Python解释器和Python编辑器于一身的,但是Python编辑器中pycharm更好用,所以本教程是写给自己的,每次重新安装anaconda和pycharm的时候有的要注意的地方都记不住了1.安装anaconda1.1.去官网下载anaconda的安装包(官网:https://www.anaconda.com/products/individual)在官网下载很忙的话可以去这里https://mirrors.tuna.tsinghua.edu.cn/下1.2.安装过

  • 安卓手机如何打开.pdf(1)文件_手机pdf格式怎么使用查找功能

    安卓手机如何打开.pdf(1)文件_手机pdf格式怎么使用查找功能最近在做结算功能,需要上传发票功能,发票有电子和图片发票两种,技术这边有两种方案,一种是上传图片文件,还有一种是上传PDF格式发票文件,但是结算时财务说图片文件上面没有公司盖章,是无效的,于是把方案改为电子发票PDF和纸质发票,刚开始使用的文件管理器搜索手机内的PDF文件,在4.4系统上面打开文件管理器可以过滤掉非.pdf格式文件,在6.0及以上系统没有过滤掉,用的是intent打开u…

  • GBDT算法

    GBDT算法

    2021年11月19日
  • WPF 用代码实现WrapPanel右侧自动对齐(解决多余空白问题)

    WPF 用代码实现WrapPanel右侧自动对齐(解决多余空白问题)未处理前效果:处理后效果:<BorderBackground=”{StaticResourceBorderBg}”BorderThickness=”2″BorderBrush=”{StaticResourceBorderBrush}”CornerRadius=”5″Padding=”5″x:Name=”SvKeyWords”Margi…

  • 5.6 读和写流

    5.6 读和写流

发表回复

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

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