According to the C++ standard, a class that has virtual functions cannot have a trivial copy constructor:
A copy/move constructor for class X is trivial if it is not user-provided and if
— class X has no virtual functions (10.3) and no virtual base classes (10.1), and
— the constructor selected to copy/move each direct base class subobject is trivial, and
— for each non-static data member of X that is of class type (or array thereof), the constructor selected to copy/move that member is trivial;
otherwise the copy/move constructor is non-trivial.
Now, imagine a class hierarchy that satisfies all the mentioned conditions except the 'no virtual functions' condition:
struct I
{
virtual void f() = 0;
};
struct D final : I
{
void f() override
{
}
};
From an implementation's point of view those classes contain only a pointer to the virtual dispatch table. And the base class does not have any user-declared constructors, and the derived class is final, so the mentioned pointer can always have a constant value. Given all that, the copy constructor can be trivial, yet the standard explicitly forbids treating it as such.
On the other hand, the conditions of treating such classes as trivially destructible are met. The class does not declare a virtual destructor and uses implicitly-defined destructors.
Requiring triviality of destructors looks like mandating an optimization - implicitly defined destructors should not restore pointers to the virtual table in this case.
But such an optimization goes half-way in my opinion; classes with virtual functions still cannot be memcopied, even if they can be trivially destructed.
The questions:
Are there any reasons I did not think of from an implementation perspective why such classes should have non-trivial copy-constructors?
Are there any reasons the restrictions on triviality for copy-constructors cannot be relaxed in the standard?