前言
今天研究下智能指针的垃圾回收,以及反射的基础知识。
智能指针
参考文献
为啥要用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 | class NativeClass |
我们可以直接通过共享指针来获取成员变量,这是因为TSharedPtr
重写了->
符号,返回的就是「被包裹的」实例本身:
1 | // File: SharedPointer.h |
所谓
a->b
,本质也就是(*a).b
,所以重写->
,要返回的是*a
的结果。在重写之前,->
肯定返回的是*a
。
超出定义域之后,引用计数会自动减一。有时间再看源码吧,估计又是Cocos2dx的Ref那一套。
易法
派生类 $\Longrightarrow$ 基类
支持隐式转换,直接等于即可。
1 | TSharedPtr<Base> pBase; |
基类 $\Longrightarrow$ 派生类
需要用到StaticCastSharedPtr<T>()
函数。
1 | TSharedPtr<Derived>pDerived = StaticCastSharedPtr<Derived>(pBase); |
const $\Longrightarrow$ mutable
使用ConstCastSharedRef
和ConstCastSharedPtr
将常量智能指针转换成可变智能指针。
TSharedFromThis
继承于该类,会提供一个AsShared()
,可以方便的从原始指针转换为一个共享指针。
1 | class Test: public TSharedFromThis<Test> |
反射
参考文献
总览
反射系统是选择加入的,只有主动标记的类型、属性、方法会被反射系统追踪,UnrealHeaderTool会收集这些信息,生成用于支持反射机制的C++代码,然后再编译工程。
头文件与GENERATED_BODY()
GENERATED_BODY()
的内容是被定义在UHT生成的头文件中的。