智能指针库:减轻内存分配与追踪负担 ,C++11中智能指针的定义实现
- 共享指针TSharedPtr
- 共享引用 TSharedRef(不可为空)
- 弱指针 TWeakPtr
- 助手类与函数
助手类与函数
MakeShareable()
-用于从C ++指针初始化共享指针(启用隐式转换)TSharedFromThis
-您可以从this派生自己的类,以从“this
”获取TSharedRef
StaticCastSharedRef()
-静态转换实用工具函数,通常用于向下转换为派生类型。ConstCastSharedRef()
-将“const
”引用转换为“可变”智能引用StaticCastSharedPtr()
-动态强制转换实用程序函数,通常用于向下转换为派生类型。ConstCastSharedPtr()
-将“const
”智能指针转换为“可变”智能指针
使用共享引用TSahredRef和指针TSharedPtr等的好处:
- 干净的语法:可以像常规C ++指针一样复制,取消引用和比较共享指针。
- 防止内存泄漏: 对象在没有共享引用的时候
- 弱引用: 弱指针可以安全地检查对象何时被破坏
- 线程安全:可以从多个线程安全中访问的“安全线程”
- 无处不在: 可以创建指向几乎任何对象类型的共享指针
- 运行时安全: 共享引用永远不会为null,并且始终可以取消引用
- 没有参考周期(ReferenceCycle): 使用弱指针来破坏参考周期
- 赋予意图:可以轻松地从
观察者
告诉对象所有者
owner - 性能: 共享指针具有最小的开销,所有操作都是恒定时间
- 强大的功能:支持’const’,将声明转发给不完整的类型,类型转换等
- 内存:只有64位C ++指针大小的两倍(加上共享的16字节引用控制器)
局限性:
- 共享指针与虚幻对象(
UObject
类)不兼容! - 当前仅具有常规析构函数的类型(无自定义删除器)
- 目前尚不支持动态分配的数组(例如
MakeSharable(new int32 [20])
) - 尚不支持将
TSharedPtr
/TSharedRef
隐式转换为bool
和(boost:shared_ptr
,std :: shared_ptr
)之类的区别: - 类型名称和方法名称与Unreal的代码库更加一致
- 必须使用
Pin()
将弱指针转换为共享指针(无显式构造函数)
-线程安全功能是可选的,而不是强制的 TSharedFromThis
返回共享的参考,而不是共享的指针- 省略了某些功能(例如use_count(),unique()等)
- 不允许例外(已省略所有相关功能)
- 尚不支持自定义分配器和自定义删除功能
使用Tips:
- 尽可能使用
TSharedRef
代替TSharedPtr
-永远不能为nullptr
! - 可以调用TSharedPtr :: Reset()`释放对对象的引用(并可能取消分配)
- 使用
MakeShareable()
辅助函数隐式转换为TSharedRefs
或TSharedPtrs
- 永远不能重置
TSharedRef
或将其分配给nullptr
,但是可以为其分配新对象 - 共享的指针假定对象的所有权-无需调用
delete self
! - 通常,在将C ++指针传递给新的共享指针时,应该“操作新的”
- 将智能指针作为函数参数而不是
TWeakPtr
传递时,请使用TSharedRef
或TSharedPtr
- 智能指针的“线程安全”版本要慢一些-仅在需要时使用它们
- 可以转发声明不完整类型的共享指针,就像您期望的那样!
- 兼容类型的共享指针将隐式转换(例如,向上转换)
- 可以为
TSharedRef <MyClass>
创建typedef
以使其更容易键入 - 为了获得最佳性能,尽量减少对
TWeakPtr :: Pin
的调用(或对TSharedRef
/TSharedPtr
的转换) - 如果类继承
TSharedFromThis
,这个类可以将自己作为共享引用返回 - 要向下转换指向派生对象类的指针,请指向
StaticCastSharedPtr
函数 - 共享指针完全支持
'const'
对象! - 可以使用
ConstCastSharedPtr
函数使'const'
共享指针可变
下面是 SharedPointerTesting.inl
文件中的一些使用的UE4智能指针的测试示例
inl文件:inl文件是内联函数的源文件。
内联函数通常在C++头文件中实现,但是当C++头文件中内联函数过多的情况下,
我们想使头文件看起来简洁点,像普通函数那样将内联函数声明和函数定义放在头文件和实现文件中,
具体做法将是:将内联函数的具体实现放在inl文件中,然后在该头文件末尾使用#include引入该inl文件。
/*
"->"箭头和"(*)."对于智能指针指向的对象的修改都是有效的,
对于多个智能指针指向的对象,释放其中一个智能指针,其指向的对象并不会被销毁
*/
{
// Test arrow operator
struct FSharedTest
{
bool bFoo;
};
TSharedPtr< FSharedTest, Mode > SharedArray( new FSharedTest() );
SharedArray->bFoo = true;
// Test dereference operator
( *SharedArray ).bFoo = false;