3

Here, in this code, the size of ob1 is 16 which is fine(because of the virtual pointer) but I can't understand why the size of ob2 is 24.

#include <iostream>
using namespace std;
class A {
    int x;
};
class B {
    int y, z;
};
class C : virtual public A {
    int a;
};
class D : virtual public B {
    int b;
};
int main() {
    C ob1;
    D ob2;
    cout << sizeof(ob1) << sizeof(ob2) << "\n";
}

I expect the size of ob2 as 20, but the output is 24

17
  • 1
    The virtual mechanism requires some overhead. Some compilers place that overhead into the structure. Commented Aug 13, 2019 at 15:48
  • You should make a habit of always terminating your output by either '\n' or std::endl. Commented Aug 13, 2019 at 15:49
  • 1
    There's usually a vtable pointer introduced with virtual inheritance. That might explain the difference in size, Commented Aug 13, 2019 at 15:50
  • 1
    @πάνταῥεῖ: "There's usually a vtable pointer ". Is virtual inheritance introducing a vtable pointer? I don't believe! Commented Aug 13, 2019 at 16:01
  • I expect the size of ob2 as 20, but the output is 24 What's your exact platform? Likely something in the internals of the object has an 8-byte alignment requirement. Or the platform itself imposes an 8-byte alignment requirement in general. Commented Aug 13, 2019 at 16:10

2 Answers 2

8

One possible layout for objects of type D is:

+----------+
| y        |   The B subobject (8 bytes)
| z        |
+----------+
| vptr     |   vtable pointer (8 bytes)
|          |
+----------+
| b        |   4 bytes
+----------+
| unused   |   4 bytes (padding for alignment purposes)
+----------+

That would make sizeof(ob2) 24.

Alignment requirements are defined by an implementation. Most of the time, the size of the largest member object or subobject dictates the alignment requirement of an object. In your case, the size of the largest object, the vtable pointer, is 8 bytes. Hence, the implementation aligns objects at 8 bit boundaries, adding padding when necessary.

Sign up to request clarification or add additional context in comments.

4 Comments

Obviously the correct answer. Perhaps you can elaborate on the for alignment purposes bit?
I am interested in the question: Why we need a runtime vtable pointer in that case. I can't catch the point why it is dependent on runtime here as the inheritance hierarchy is fully known at compile time. Thanks... maybe another question :-)
@Klaus, yes, that would be another question.
@Klaus Inheritance relations is not more known at compile time than function members are. Virtual stuff can be overridden in derived classes unlike non virtual stuff.
2

To implement the virtual inheritance, D contains as data member a pointer, which on a 64 bit system requires 8 bytes. Moreover, these 8 bytes must be aligned to a 8-byte memory boundary. This latter requirement in turn mandates that D itself be aligned to a 8-byte memory boundary. The simplest way to implement that is to make sizeof(D) a multiple of 8 by padding it with unused bytes (21-24).

1 Comment

"padding it with unused bytes" and that (almost certainly correct) hypothesis can be verified by adding a dummy data member at the end, the size of hypothesized padding, and checking that the total size doesn't change.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.