i assume its the heap, because its dynamic memory, but in ue4, i never worry about stack vs heap, because ue4 has automatic garbage collection, so i never use Malloc or anything fancy, i just let it handle the memory maintenance how it wants.
class pointers and object pointers are different things. a UClass is something available in the editor, it has default properties and all knowledge needed to create or spawn an object or actor. its like a particle effect or static mesh or any other asset in the editor that is available in the editor without running the game.
objects and actors need to be spawned or created at runtime in order to exist or be pointed to.
so you could have an Actor called Dog, and a few subclasses called Poodle and Pitbull. using a TSubclassOf, you can select the type of dog in the editor, which you want to spawn in the game.
then when the game runs, you can spawn a hundred dogs of that type, and have an actor pointer which points to a specific dog. so even if there are 50 poodles, you can make a single poodle do a backflip, by calling a function using that actor pointer.
with a class pointer, you are not talking about a specific dog in the world, you are talking about a breed of dog, so you cant tell that breed of dog to do a backflip, you can only check its default properties, like how strong its biteforce is.
so in summary, TSubclassOf is a specific type of UClass pointer, which narrows down the list of available classes in the details panel, to a specific branch in the hierarchy of classes. it exists to give designers a choice between sublcasses of actors or objects, without having to change or compile any code.