Clarification of UPROPERTY() and UFUNCTION Please

When I started learning UE c++ some time ago, I was made to believe that in order to avoid memory leaks and other bad things, I should use UPROPERTY(…) and UFUNCTION(…) so the garbage collector can do its magic and have ALL methods and properties in my classes use these macros.

I now have reason to question my knowledge. For example, Having now incorperated the Mediator design pattern into my code, I no longer expose any properties or functions to my Widgets under binding unless it goes through my Mediator class.

This is great (and super tidy), but it means all of my other classes now have only empty UPROPERTY() and UFUNCTION() macros.

I thought this was still needed for UE’s garbage collector, but when I started using TTuple and TPair, I discovered that these cannot have the UPROPERTY() macro anyway, so I guess the macros are not strictly needed for UE to run properly - Unless using TTuple and TPair is causing a memory leak?

Can someone knowledgeable please clarify if its OK to remove all the empty Macros. I am so used to seeing and using them, that I use them visually to see if a property/method is part of the child class, or lack of macro means its an overridden method, but Im wondering if removing all the unnecessary macro definitions will improve performance and efficiency of my code.

Thanks

First off, UFUNCTION has zero impact on garbage collection. You only need to use that macro if you’re trying to do something with Blueprints or dynamic delegates. There could be others, but those are the two primary cases.

The UPROPERTY macro is definitely the easiest way to make sure things are visible to the garbage collector. But instead of leaks, what you’ll find is that your objects start disappearing when you don’t expect them to.
This could be okay if something else is making sure that the object you’re referencing is staying alive. For example, if you’re pointing at an ActorComponent in your tuple you might be okay because the Actor that owns the component will keep it alive (assuming that your tuple is also cleared if the Actor or component is destroyed).

Is it okay? Maybe, there are so many factors that go into it. There’s no downside to the macro being there. You’ll need it for anything you want to do that relies on reflection. Garbage collection is only one, Blueprints, Editor UI, serialization for data or save games are a number of others that you’d need those macros (and they might be empty).