When a base class is virtual, only one subobject of the base class belongs to each full object. Also, the constructors and destructors are invoked only once, and called from the most-derived class. However, such objects behave unspecified when being assigned. For example:
struct Base{
  char *name;
  Base(const char *n) : name(strdup(n)){}
  Base& operator= (const Base& other){
   free (name);
   name = strdup (other.name);
   return *this;
  }
};
struct A:virtual Base{
  int val;
  A():Base("A"){}
};
struct B:virtual Base{
  int bval;
  B():Base("B"){}
};
struct Derived:public A, public B{
  Derived():Base("Derived"){}
};
void func(Derived &d1, Derived &d2)
{
  d1 = d2;
}
The C++ standard specifies that ‘Base::Base’ is only called once when constructing or copy-constructing a Derived object. It is unspecified whether ‘Base::operator=’ is called more than once when the implicit copy-assignment for Derived objects is invoked (as it is inside ‘func’ in the example).
G++ implements the “intuitive” algorithm for copy-assignment: assign all
direct bases, then assign all members.  In that algorithm, the virtual
base subobject can be encountered more than once.  In the example, copying
proceeds in the following order: ‘name’ (via strdup),
‘val’, ‘name’ again, and ‘bval’.
If application code relies on copy-assignment, a user-defined copy-assignment operator removes any uncertainties. With such an operator, the application can define whether and how the virtual base subobject is assigned.