大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新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账号...