This is perfectly safe. Visual components aren't really any different from non visual components in terms of how instance variables are handled.
Reference counting of dynamic arrays can be thought of simply as automatic memory management of the array. Note that I said "of the array". Reference counting of dynamic arrays implies nothing about memory management of its elements.
An element of a dynamic array of TMyVisualComponent is simply a variable that holds a reference to an object. It's no different from a local variable of type TMyVisualComponent or a field of a class of type TMyVisualComponent.
Consider the following two examples:
type
TMyClass1 = class
private
FObj: TMyVisualComponent;
end;
TMyClass2 = class
private
FArr: TArray<TMyVisualComponent>;
end;
Into FObj is placed a reference to an instance whose lifetime is managed elsewhere. Likewise into FArr is placed references to multiple instances whose lifetimes are managed elsewhere.
When an instance of TMyClass1 is destroyed, nothing happens to the instance referred to by FObj. All that happens is that the instance of TMyClass1 is destroyed, and since it contains the variable FObj, then that variable too is destroyed. Note that I said "variable". The variable FObj is destroyed, the object to which it refers is not affected.
Similarly, when an instance of TMyClass2 is destroyed, the array FArr is destroyed, but nothing happens to the objects that it refers to.
One final wrinkle is that under the ARC compilers, all references to classes are reference counted. So what I said above needs to be modified to include reference counting of the instances of TMyVisualComponent. But since there are other parties that hold references to these instances of TMyVisualComponent, then they would remain alive throughout.
In summary then, simply think of TArray<TMyVisualComponent> as nothing more than multiple variables of TMyVisualComponent defined at the same scope.