UE垃圾回收-纳入被自动GC机制管理的条件


文章目录

  • 一、UObject成员变量必须用 UPROPERTY 修饰
  • 二、实现 AddReferencedObjects 接口
  • 三、结构体继承 FGCObject 并实现 AddReferencedObjects
  • 总结
  • 注意事项:


一、UObject成员变量必须用 UPROPERTY 修饰

如果 UObject 类型的成员变量未被标记为 UPROPERTY,GC 将无法识别其引用,导致对象可能被错误回收。

// MyClass.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "MyClass.generated.h"

UCLASS()
class UMyClass : public UObject
{
    GENERATED_BODY()

public:
    // 未使用 UPROPERTY 修饰 → 可能被GC回收
    UObject* UnreferencedObject;

    // 使用 UPROPERTY 修饰 → GC会追踪引用
    UPROPERTY()
    TObjectPtr<UObject> ReferencedObject;
};

验证方式

  • UnreferencedObject 未被其他引用持有,其指向的对象可能在GC时被回收。
  • ReferencedObject 会始终被GC追踪,只要 UMyClass 实例存活。

二、实现 AddReferencedObjects 接口

当需要手动管理非 UPROPERTY 成员变量或复杂引用关系时,可重写 AddReferencedObjects 方法。

// MyActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS()
class AMyActor : public AActor
{
    GENERATED_BODY()

public:
    // 非 UPROPERTY 成员变量
    UObject* OtherObject;

protected:
    // 重写 AddReferencedObjects 手动添加引用
    virtual void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector) override
    {
        Collector.AddReferencedObject(OtherObject);
        Super::AddReferencedObjects(InThis, Collector);
    }
};

关键点

  • 即使 OtherObject 未被 UPROPERTY 修饰,通过 AddReferencedObjects 手动添加引用,GC 会将其标记为“被引用”。
  • 适用于动态管理对象引用的场景(如对象池、缓存)。

三、结构体继承 FGCObject 并实现 AddReferencedObjects

如果结构体(struct)包含 UObject 指针且需要被GC保护,必须继承 FGCObject 并手动添加引用。

// MyStruct.h
#pragma once
#include "UObject/GCObject.h"

// 自定义结构体继承 FGCObject
class FMyStruct : public FGCObject
{
public:
    // 结构体中持有 UObject 指针
    UObject* MyObject;

    // 必须重写 AddReferencedObjects
    virtual void AddReferencedObjects(FReferenceCollector& Collector) override
    {
        Collector.AddReferencedObject(MyObject);
    }
};

// 使用示例
void ExampleUsage()
{
    FMyStruct MyStructInstance;
    MyStructInstance.MyObject = NewObject<UObject>();
    // 只要 MyStructInstance 存在,MyObject 不会被GC回收
}

关键点

  • 适用场景:非 USTRUCT 的自定义原生结构体(如工具类、独立于UObject系统的模块)。
  • 比 USTRUCT:若结构体是 USTRUCT,且其成员用 UPROPERTY 标记,则无需继承 FGCObject,例如:
USTRUCT()
struct FMySafeStruct
{
    GENERATED_BODY()

    UPROPERTY()
    TObjectPtr<UObject> SafeObject; // 自动被GC追踪
};

总结

场景 方法 代码示例
UObject成员变量引用 使用 UPROPERTY 标记 UPROPERTY() TObjectPtr Ref;
手动管理复杂引用 重写 AddReferencedObjects virtual void AddReferencedObjects(…) { Collector.AddRef(Obj); }
结构体保护UObject引用 继承 FGCObject 并实现接口 struct FMyStruct : FGCObject { … }

注意事项:

  1. USTRUCT 的特殊性
    • 若结构体是 USTRUCT,其内部 UObject 指针必须用 UPROPERTY 修饰,否则无法自动追踪引用。
    • 原生结构体(非 USTRUCT)必须通过 FGCObject 手动管理引用
  2. 性能影响
    • AddReferencedObjects 在GC时会被频繁调用,确保代码高效,避免复杂逻辑。
  3. 循环引用
    • 即使通过上述方法保护对象,若对象间形成循环引用(如A引用B,B引用A),需手动打破循环(如使用弱指针 TWeakObjectPtr)。

你可能感兴趣的:(ue4)