UE 5.3 C++ 对垃圾回收的初步认识
一.UObject的创建
UObject 不支持构造参数。
所有的C++ UObject都会在引擎启动的时候初始化,然后引擎会调用其默认构造器。如果没有默认的构造器,那么 UObject 将不会编译。
有修改父类参数的需求,就使用指定带参构造
// Sets default values for this actor's properties
AMyActor();
//
AMyActor(const FObjectInitializer& ObjectInitializer);
创建
1. NewObject<T>();
虚幻会管理,它重载了new 和 delete。
myObject = NewObject<UBaseObject>();
2. CreateDefaultSubobject<T>();
RootComponent = CreateDefaultSubobject<USceneComponent>("Root");
只是上一个更通用,下面这个在构造函数里才使用,来创建和管理组件。
二.测试垃圾回收
在你Actor的头文件的中,声明一个UObject·。
UCLASS()
class MYPROJECT_API UBaseObject :public UObject
{
GENERATED_BODY()
public:
UBaseObject();
UBaseObject(const FObjectInitializer& ObjectInitializer);
virtual ~UBaseObject();
int32 Health = 666;
};
并在Actor里声明它。
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UFUNCTION(BlueprintCallable)
void InitBaseObject();
UFUNCTION(BlueprintCallable)
int32 GetBaseObjectHealth();
//为了避免对象被回收
//UPROPERTY() //有对象引用了,就不会被回收
UBaseObject* myObject = nullptr;
};
CPP里实现
void AMyActor::InitBaseObject()
{
myObject = NewObject<UBaseObject>();
myObject->AddToRoot();
}
int32 AMyActor::GetBaseObjectHealth()
{
if (myObject)
{
return myObject->Health;
}
return -1;
}
UBaseObject::UBaseObject()
{
UE_LOG(LogTemp, Warning, TEXT("初始化了"));
}
UBaseObject::UBaseObject(const FObjectInitializer& ObjectInitializer)
{
UE_LOG(LogTemp, Warning, TEXT("初始化了2"));
}
UBaseObject::~UBaseObject()
{
UE_LOG(LogTemp, Warning, TEXT("垃圾回收"));
}
测试
一旦按下3,垃圾回收。自己的UObject就会被回收掉。
解决方案,加上UPOPERTY,让它被对象引用。
//为了避免对象被回收
UPROPERTY() //有对象引用了,就不会被回收
UBaseObject* myObject = nullptr;
AddtoRoot,强制不被回收。和允许回收。少用这个方法。
void AMyActor::InitBaseObject()
{
myObject = NewObject<UBaseObject>();
myObject->AddToRoot();
}
注:标记UPROPERTY 会自动加入root set 阻止垃圾回收
一个Up标记object类指针变量,当指向null时,object会进行析构,自动进行垃圾回收
一个非标记的object类变量,当未添加AddToRoot时,会被下一次垃圾回收,留下野指针。
你通常需要保持对希望保持活跃的任何Object的`UPROPERTY`引用,或者将指向它的指针存储在`TArray`或其他引擎容器类中。