RAII技术
UObject本身可以支持垃圾回收,做内存释放
UE4几乎所有类都继承于UObject,当生命周期结束,引擎会自动释放资源对象,无需手动释放。
不继承于UObject,RawC++,不提供垃圾回收,需要手动管理内存。
默认创建销毁方式是new/delete malloc/free
> new 会调用构造,delete会调用析构
TSharedPtr
TSharedRef
TWeakPtr
TUniquePtr
+ 双层判定
+ 先判定智能指针是否有效
+ 再判定智能指针管理的对象是否有效
# TSharedPtr 和 TSharedRef
在Unreal Engine中,`TSharedPtr`和`TSharedRef`都是引用计数的智能指针,但它们在语义和保证上有所不同。以下是它们之间的主要差异和转换方法:
1. **主要差异**:
- `TSharedPtr`是一个可以为null的智能指针。
- `TSharedRef`是一个不能为null的智能指针。使用它时,你有一个强烈的保证指针指向的对象是有效的。
2. **从`TSharedPtr`转换为`TSharedRef`**:
要从`TSharedPtr`转换为`TSharedRef`,你必须确保`TSharedPtr`不是null,因为`TSharedRef`不能引用空指针。你可以使用`ToSharedRef`方法进行转换。
```cpp
TSharedPtr<MyClass> MySharedPtr = /*...*/;
if (MySharedPtr.IsValid())
{
TSharedRef<MyClass> MySharedRef = MySharedPtr.ToSharedRef();
}
```
3. **从`TSharedRef`转换为`TSharedPtr`**:
这是一个直接的操作,因为`TSharedRef`总是有效的。可以直接使用赋值操作。
```cpp
TSharedRef<MyClass> MySharedRef = /*...*/;
TSharedPtr<MyClass> MySharedPtr = MySharedRef;
```
4. **注意事项**:
在转换之前,一定要确保`TSharedPtr`是有效的。在尝试将其转换为`TSharedRef`之前,通常应该检查其有效性。否则,如果`TSharedPtr`是null,转换操作将导致运行时断言。
总之,`TSharedPtr`和`TSharedRef`之间的转换是可能的,但转换过程中需要考虑智能指针的有效性。你可以根据你的需求和上下文选择使用哪种类型的智能指针,但在进行转换时要小心。
# 继承体系下的转换
```cpp
//父类转为子类
子类 = StaticCastSharedPtr<子类>(父类);
//子类转为父类
父类 = 子类
```
# TSharedFromThis
`TSharedFromThis`是一个非常实用的工具,它使对象能够安全地创建自身的`TSharedRef`或`TSharedPtr`。下面是一些典型的使用场景:
1. **事件和回调**:
当一个对象需要注册自身到某个事件或回调中,并且该事件/回调接收一个`TSharedRef`或`TSharedPtr`作为参数时,`TSharedFromThis`就可以发挥作用。
例如,一个UI窗口类可能想要注册自己的回调方法到一个按钮的点击事件中。该窗口类可以使用`TSharedFromThis`来安全地传递自身的引用给事件。
2. **工厂方法**:
对于某些设计模式,如工厂方法模式,对象可能需要创建并返回其子对象的引用。如果这些子对象需要访问或与其父对象交互,它们可能需要一个父对象的`TSharedRef`或`TSharedPtr`。在这种情况下,`TSharedFromThis`允许父对象安全地传递其引用。
3. **链式操作**:
对于支持链式方法调用的类,`TSharedFromThis`允许每个方法都返回一个当前对象的引用,从而可以连续地调用其他方法。
```cpp
class MyBuilder : public TSharedFromThis<MyBuilder>
{
public:
TSharedRef<MyBuilder> SetParameterA(int value)
{
// set the value
return SharedThis(this);
}
TSharedRef<MyBuilder> SetParameterB(float value)
{
// set the value
return SharedThis(this);
}
};
// 使用链式调用
MyBuilderInstance->SetParameterA(10)->SetParameterB(5.5f);
```
4. **延迟操作**:
当某个对象计划在未来的某个时间执行操作,并且需要在该时间点访问自身时,`TSharedFromThis`也很有用。例如,某个对象可能希望在延迟几秒后执行某个操作,而在那时,我们需要确保该对象仍然存在并且可以被安全地访问。
5. **委派或订阅系统**:
在某些系统中,例如一个订阅/发布模式,对象可能需要将自身订阅到某个主题或频道。此时,为了通知或回调,它需要将自身的引用传递给订阅系统,`TSharedFromThis`在这里就非常有用。
通过这些例子,你可以看到`TSharedFromThis`为那些需要在某些时点或在某些上下文中提供自身引用的对象提供了一个非常安全和方便的方式。这为避免悬挂指针和非法引用等常见问题提供了一个很好的解决方案。