【UE4学习】20200825 智能指针和反射

前言

今天研究下智能指针的垃圾回收,以及反射的基础知识。

智能指针

参考文献

为啥要用UE4提供的智能指针

最主要的原因:不是啥类都是继承于UObject的,这部分类本是无法被UE4垃圾回收的,同样,USTRUCT也是没办法被垃圾回收的。如果想要让UE4的垃圾回收管理这部分的内存,那么使用UE4提供的智能指针就好了。

另外:

  • std::shared_ptr不是在所有的平台都能用的
  • 配合UE4的容器类使用,酸爽

然而,还是有一些性能上的缺陷,例如:

  • 创建和复制智能指针比创建和复制原始C++指针需要更多开销
  • 保持引用计数增加基本运算的周期。
  • 部分智能指针占用的内存比原始的C++更多。
  • 引用控制器有两个堆分配。使用 MakeShared 代替 MakeShareable 可避免二次分配,并可提高性能。

都有哪些智能指针

  • TSharedPtr
  • TSharedRef
  • TWeakPtr
  • TUniquePtr

几个的区别

Type 解释 内存占用 性能
TSharedPtr 引用计数的非侵入式的权威智能指针 默认是裸指针两倍,但是多出了控制块的内存 有一定的内存消耗,大约是两倍
TSharedRef 引用计数的非侵入式的权威智能引用(只是不能为null) 同上 同上
TWeakPtr 引用计数的、非侵入式弱指针引用 两倍的裸指针大小,有一个指针指向控制块 比Tsharedptr略慢
TUniquePtr 专属所有权智能指针,只能转移,不能复制 默认和裸指针相同,有状态的删除其和采用函数指针实现的删除器会增加尺寸 基本裸指针相同

TSharedPtr

使用方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class NativeClass
{
public:
int32 Value;
}

void TestSharedPtr()
{
// 声明并定义
TSharedPtr<NativeClass> MyNativeClass = MakeSharable(new NativeClass());
// 判空
if( MyNativeClass.IsValid() || MyNativeClass.Get() )
{
// 直接访问成员变量,这里有点匪夷所思
int32 Value = MyNativeClass->Value;
// 使用复制构造函数来复制指针,经试验,复制完会把引用计数 +1
TShared<NativeClass> MyNativeClass2 = MyNativeClass;
// 获取引用计数
int32 RefCount = MyNativeClass.GetSharedReferenceCount();
// 销毁
MyNativeClass.Reset();
}
}

我们可以直接通过共享指针来获取成员变量,这是因为TSharedPtr重写了->符号,返回的就是「被包裹的」实例本身:

1
2
3
4
5
6
// File: SharedPointer.h
FORCEINLINE ObjectType* operator->() const
{
check( IsValid() );
return Object;
}

所谓a->b,本质也就是(*a).b,所以重写->,要返回的是*a的结果。在重写之前,->肯定返回的是*a

超出定义域之后,引用计数会自动减一。有时间再看源码吧,估计又是Cocos2dx的Ref那一套。

易法

派生类 $\Longrightarrow$ 基类

支持隐式转换,直接等于即可。

1
2
3
TSharedPtr<Base> pBase;
TSharedPtr<Derived> pDerived = MakeSharable(new Derived());
pBase = pDerived;

基类 $\Longrightarrow$ 派生类

需要用到StaticCastSharedPtr<T>()函数。

1
2
3
TSharedPtr<Derived>pDerived = StaticCastSharedPtr<Derived>(pBase);
// 判空
bool valid = pDerived.IsValid();

const $\Longrightarrow$ mutable

使用ConstCastSharedRefConstCastSharedPtr将常量智能指针转换成可变智能指针。

TSharedFromThis

继承于该类,会提供一个AsShared(),可以方便的从原始指针转换为一个共享指针。

1
2
3
4
5
6
7
8
9
10
11
class Test: public TSharedFromThis<Test>
{

}

void TestSharedFromThis()
{
TSharedPtr<Test> a = MakeSharable(new Test());
Test* InnerPointer = a.Get();
TSharedPtr<Test> b = InnerPointer.AsShared();
}

反射

参考文献

总览

反射系统是选择加入的,只有主动标记的类型、属性、方法会被反射系统追踪,UnrealHeaderTool会收集这些信息,生成用于支持反射机制的C++代码,然后再编译工程。

头文件与GENERATED_BODY()

GENERATED_BODY()的内容是被定义在UHT生成的头文件中的。

Buy Me A Coffee / 捐一杯咖啡的钱
分享这篇文章~
0%
//