CreateDefaultSubobject is the way to add components in the constructor. The most obvious benefit to this is that the components will be editable in the editor and blueprint-derived classes. There are downsides to this, such as not being able to drive the component spawning via variables. Afaik it has to do with the way how objects are spawned in Unreal (the gist of it from what I can tell is that the “ClassDefaultObject” is created based on C++ constructor and newly spawned actors are copies of the CDO rather than newly created). Blueprint constructors work differently and are more flexible, i.e allow editing on per-instance basis.
NewObject is the way to handle spawning during runtime i.e gameplay, and yes, they need to be registered. If you want to dynamically spawn components in the editor via C++ instead of Blueprint, you’d need to do so with i.e PostEditChangeProperty and such functions, as well as get yourself accustomed to property specifiers like transients and look up which flags are set in the SpawnActor function to know what also to add so editor functions like Undo would work as expected.