Yes, your understanding is correct but it would be hard to tell scenarios where virtual inheritance is really reasonable and even in those cases the problem can usually be solved with something else that is more simple.
In your case your D instance will be a composition of a C, a B and a single A instance. Since both A and B can make part in different scenarios with different compositions where A is inherited virtually by many classes (maybe even more classes than A and B) it is not clear how to lay out for example the building blocks of a D instance in memory. For this reason the code compiled for classes B and C usually make use of utility pointers or offsets (1 pointer per instance, one for B and one for C) that point to the A instance that is shared by the code of different classes that inherit virtually from class A. This takes up extra space in your D instance and makes your code less effective by playing around with those pointers.
Another ugly implementation detail is that in case of your D class when you create/initialize an instance of D both your B and C instances are "racing" for calling the constructor of class A from their constuctors. For this reason your D instance will also contain a bool variable that indicates whether someone has already called the ctor of A from its constructor. One of the ctors of B and C will win and set this bool variable tot true so the following attempts coming from the ctors of other "virtual descendants" simply bail out after checking that particular bool value.
Virtual inheritance is simply ugly and avoid whenever possible.