# 智能指针
UObject 本身就可以帮我们做回收,做释放的,为了可以在更好释放内存,避免出现野指针,而出现智能指针
# 为什么使用虚幻 4 的智能指针库?
- std::shared_ptr 不是在所有的平台都能用的
- 可以和其它虚幻容器及类型无缝协作
- 更好的控制平台特性,包括线程处理和优化
# 优点
- 可以像常规的 C++ 指针那样复制,解引用,比较共享指针等
- 防止内存泄漏:当没有共享引用时资源自动删除
- 包含了可以通过多线程安全地进行访问的 “线程安全” 版本
- 可以创建任何类型的对象的共享指针
- 支持针 “const”、前置声明的不完全类型、类型转换等
# 如何使用智能指针
智能指针的主要类型分为:TSharedPtr, TSharedRef, TWeakPtr, 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 24 25 26 27
| class TestA { public: int32 a; float b; };
void TestSharedPtr() { TSharedPtr<TestA>MyTestA; MyTestA = MakeShareable(new TestA()); if (MyTestA.IsValid()||MyTestA.Get()) { int32 a = MyTestA->a; TSharedPtr<TestA>MyTesta = MyTestA; int32 Count = MyTestA.GetSharedReferenceCount(); MyTesta.Reset(); } };
|
使用 TSharedRef(共享引用)用法
""1 2 3 4 5 6 7 8 9 10
| voidTestSharedRef() {
TSharedRef<TestA>MyTestB(new TestA());
int32 a= MyTestB->a; int32 b= (*MyTestB).a;
MyTestB.Reset(); };
|
TSharedPtr 和 TSharedRef 之间的相互转换
""1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| voidATestSharedRefAndPtr() {
TestA* MyTestC=new TestA();
TSharedPtr<TestA>MyTestA;
TSharedRef<TestA>MyTestB(new TestA());
MyTestA= MyTestB;
MyTestA= MakeShareable(MyTestC);
MyTestB= MyTestA.ToSharedRef(); };
|
使用 TWeakPtr(弱指针)用法
""1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| voidTestTWeakPtr() {
TSharedPtr<TestA> _TestA_ptr= MakeShareable(new TestA());
TSharedRef<TestA> _TestA_ref(new TestA);
TWeakPtr<TestA>Test_e;
TWeakPtr<TestA>Test_B(_TestA_ptr);
TWeakPtr<TestA>Test_C(_TestA_ref);
Test_e= Test_B; Test_e= Test_C;
Test_e=nullptr;
TSharedPtr<TestA> NewTest(Test_e.Pin()); if (NewTest.IsValid()||NewTest.Get()) {
NewTest->a; } };
|
# 共享指针:基类与派生类的转换
""1 2 3 4 5 6 7 8
| classFather{ public:int32 a= 10; };
classChild:public Father { public:int32 b= 20; };
|
派生类转换为基类
""1 2 3 4 5 6
| TSharedPtr<Father>_father;
TSharedPtr<Child>_child= MakeShareable(new Child);
_father= _child;
|
基类转换为派生类
""1 2 3 4 5 6 7
| TSharedPtr<Child>_child= StaticCastSharedPtr<Child>(_father);
if (_child.IsValid()) { _child->b; }
|
常量基类转换为派生类
""1 2 3 4 5 6 7 8 9 10 11
| const TSharedPtr<Father>const_father= MakeShareable(new Child);
TSharedPtr<Father>const_father_a= ConstCastSharedPtr<Father>(_father);
TSharedPtr<Child>_child_a= StaticCastSharedPtr<Child>(_father);
if (_child_a.IsValid()) { _child_a->b; }
|
# 使用 TSharedFromThis
声明一个类 Test 继承自 TSharedFromThis<Test>
""1 2 3 4 5
| classTestAA:public TSharedFromThis<TestAA>{ public:void print() { }; };
|
为什么原生的类要继承自 TSharedFromThis<>
- TSharedFromThis 是支持线程安全的。
- TSharedFromThis 里面会保存一个弱引用,可以通过这个弱引用转换为共享指针。
# 用法
""1 2 3 4 5 6 7 8 9 10 11
| TSharedPtr<TestAA>test_a= MakeShareable(new TestAA);
test_a->print();
TestAA* testb= test_a.Get();
if (testb) { TSharedPtr<TestAA>testc= testb->AsShared(); }
|
# 注意事项:
- 避免将数据作为 TSharedRef 或 TSharedRef 参数传到函数,此操作将因取消引用和引用计数而产生开销。相反,建议将引用对象作为
const &
进行传递。 - 可将共享指针向前声明为不完整类型。
- 共享指针与虚幻对象 (
UObject
及其衍生类) 不兼容。引擎具有 UObject
管理的单独内存管理系统,两个系统未互相重叠。