转自:https://docs.unrealengine.com/latest/CHN/Programming/Introduction/index.html
继承自UObject的类 系统会进行垃圾回收
UCLASS() class MyGCType : public UObject { GENERATED_BODY() };
Any UObject pointer stored in a UPROPERTY will not be collected (deleted) the next time the garbage collector is ran
void CreateDoomedObject() { MyGCType* DoomedObject = NewObject<MyGCType>(); }
When we call the above function, we create a new UObject, but we do not store a pointer to it in any UPROPERTY, and it isn’t a part of the root set. Eventually, the garbage collector will detect this object is unreachable, and destroy it.
Actors and Garbage collection
actors with UObject properties.
UCLASS() class AMyActor : public AActor { GENERATED_BODY() public: UPROPERTY() MyGCType* SafeObject; MyGCType* DoomedObject; AMyActor(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { SafeObject = NewObject<MyGCType>(); DoomedObject = NewObject<MyGCType>(); } }; void SpawnMyActor(UWorld* World, FVector Location, FRotator Rotation) { World->SpawnActor<AMyActor>(Location, Rotation); }
When we call the above function, we spawn an actor into the world. The actor’s constructor creates two objects. One gets assigned to a UPROPERTY, the other to a bare pointer. Since actors are automatically a part of the root set, SafeObject will not be garbage collected because it can be reached from a root set object. DoomedObject, however, will not fare so well. We didn’t mark it with UPROPERTY, so the collector does not know its being referenced, and will eventually destroy it.
When a UObject is garbage collected, all UPROPERTY references to it will be set to nullptr for you. This makes it safe for you to check if an object has been garbage collected or not.
使用前可以判断变量指针是否为空
if (MyActor->SafeObject != nullptr) { // Use SafeObject }
This is important since, as mentioned before, actors that have had Destroy() called on them are not removed until the garbage collector runs again. You can check the IsPendingKill() method to see if a UObject is awaiting its deletion. If that method returns true, you should consider the object dead and not use it.
UStructs
UStructs, as mentioned earlier, are meant to be a lightweight version of a UObject. As such, UStructs cannot be garbage collected. If you must use dynamic instances of UStructs, you may want to use smart pointers instead, which we will go over later.
Non-UObject References
Normal, non-UObjects can also have the ability to add a reference to an object and prevent garbage collection. To do that, your object must derive from FGCObject and override its AddReferencedObjects class.
class FMyNormalClass : public FGCObject { public: UObject* SafeObject; FMyNormalClass(UObject* Object) : SafeObject(Object) { } void AddReferencedObjects(FReferenceCollector& Collector) override { Collector.AddReferencedObject(SafeObject); } };
We use the FReferenceCollector to manually add a hard reference to the UObject we need and do not want garbage collected. When the object is deleted and its destructor is run, the object will automatically clear all references that it added.