I'm using the example in C++14 §3.11/2:
struct B { long double d; };
struct D : virtual B { char c; }
After running the snippet below in clang, g++ and VS2015
#include <iostream>
struct B { long double d; };
struct D : /*virtual*/ B { char c; };
int main()
{
std::cout << "sizeof(long double) = " << sizeof(long double) << '\n';
std::cout << "alignof(long double) = " << alignof(long double) << '\n';
std::cout << "sizeof(B) = " << sizeof(B) << '\n';
std::cout << "alignof(B) = " << alignof(B) << '\n';
std::cout << "sizeof(D) = " << sizeof(D) << '\n';
std::cout << "alignof(D) = " << alignof(D) << '\n';
}
I got the following results:
clang g++ VS2015
sizeof(long double) 16 16 8
alignof(long double) 16 16 8
sizeof(B) 16 16 8
alignof(B) 16 16 8
sizeof(D) 32 32 16
alignof(D) 16 16 8
Now, after uncommenting the virtual
in the definition of struct D
in the code above and running the code again for clang, g++ and VS2015, I obtained the following results:
clang g++ VS2015
sizeof(long double) 16 16 8
alignof(long double) 16 16 8
sizeof(B) 16 16 8
alignof(B) 16 16 8
sizeof(D) 32 32 24
alignof(D) 16 16 8
I have no doubts about the results obtained above, with one single exception: why did the sizeof(D)
increased from 16 to 24 in VS2015?
I know this is implementation defined, but there might be a reasonable explanation for this increase in size. This is what I'd like to know if possible.
If you actually make use of the virtual aspect of virtual inheritance, I think the need for the vtable pointer becomes clear. One item in the vtable is likely the offset of the start of B
from the start of D
.
Assume E
inherits virtually from B
and F
inherits from both E
and D
such that the D
inside an F
ends up using the B
inside the E
for its base class. In a method of D
that doesn't know it is a base class of F
how could you find members of B
without info stored in the vtable?
So clang and G++ changed 8 bytes of padding into a vtable pointer and you thought there was no change. But VS2015 never had that padding, so it needed to add 8 bytes for vtable pointer.
Maybe a compiler notices that the only use of the vtable pointer is in an inefficient scheme for computing the base pointer. So maybe that is optimized into simply having a base pointer instead of a vtable pointer. But that would not change the need for the 8 bytes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With