Lifetime of local objects when calling UFUNCTION from BP

I have a method (UFUNCTION) that creates a local TArray<APawn>*, pouplates it with some pawns, and returns this list to the BP caller. In the BP code I then iterate over all items returned and do some stuff. Now, a question for better understanding: Since that TArray has been defined locally in the method, from my C++ understanding it should be destroyed as soon as the method returns. Which does not seem to be happening, since I can use that array in BP after the method call.

What am I missing here?
Do I need to manually destroy the the array object somehow?

UFUNCTION creates an UObject to be used by its virtual machine; Blueprints keep their objects loaded until owner is destroyed or nothing is referencing that object anymore, that then should be garbage collected.
It defines a macro DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(OriginClass) when your className.generated.h stuff is created.

It’s possible that the UFunction object itself keeps the array loaded on memory, I don’t know for sure.
Maybe if you declare the TArray as a private member, not as a UProperty, and clear it after you call the function Node, then maybe it may work the way you intent.

The TArray is not defined as UPROPERTY.
It is just a local variable in a class method.

That’s exactly we I assumed it would be destroyed at return from that method.

The TArray local will be destroyed, but it just holds pointers to the objects, so the objects themselves aren’t automatically destroyed with it.

They would potentially be destroyed later by the garbage collector if nothing else referenced them, but all parameters/return value of a UFUNCTION are implicitly referenced by the blueprint object calling the function. Basically, by virtue of having an object type input/output pin in your blueprint graph, that pin maintains a reference to the object. Anyway in your case it doesn’t matter since actors are kept alive by the level anyway.

To put it a bit more simply - the local array is just copied out of the function and the copy is maintained by the generated code.

Makes sense, thanks :slight_smile: