C++: size of empty/non-empty virtual/non-virtual class?

Viewed 49

So I was trying to find out the size of an empty class based on whether it's empty or not empty, virtual or not virtual.

#include <iostream>

class empty_virtual_base {
    empty_virtual_base() {}
    virtual ~empty_virtual_base() {}
};

class non_empty_virtual_base {
    int a;
    non_empty_virtual_base() {}
    virtual ~non_empty_virtual_base() {}
};

class empty_base {
    empty_base() {}
    ~empty_base() {}
};

class non_empty_base {
    int a;
    non_empty_base() {}
    ~non_empty_base() {}
};

int main() {
    std::cout << "empty virtual class: " << sizeof(empty_virtual_base) << "bytes" << std::endl;
    std::cout << "non empty virtual class: " << sizeof(non_empty_virtual_base) << "bytes" << std::endl;
    std::cout << "empty normal class: " << sizeof(empty_base) << "bytes" << std::endl;
    std::cout << "non empty normal class: " << sizeof(non_empty_base) << "bytes" << std::endl;

    std::cin.get();
    return 0;
}

Output:

empty virtual class: 4 bytes
non empty virtual class: 8 bytes
empty normal class: 1 bytes
non empty normal class: 4 bytes

So I understand for a non-virtual class, it needs 1 byte for storing its potential instances' address. I'm confused why a virtual class only needs 4 bytes. I understand those 4 bytes are its v-pointers for the v-table. But doesn't it need extra 1 byte for the same purpose as a normal class?

Further, when I add an integer to both classes, virtual class becomes 8 bytes, but non-virtual class only becomes 4 bytes. Shouldn't it be 5 bytes because an integer is 4 bytes? Why is that 1 byte being neglected?

1 Answers

for a non-virtual class, it needs 1 byte for storing its potential instances' address.

To clarify: the 1 byte isn't for storing anything -- it's likely never read or written to, at all. It's so the object can have a unique address. You can't associate an address with zero bytes; otherwise multiple objects would end up with that same address, and that would cause problems.

doesn't [a class with a vtable] need extra 1 byte for the same purpose as a normal class?

No; the 4 bytes used by the vtable pointer are enough to give the class object a unique address; therefore the 1 byte isn't necessary.

non-virtual class only becomes 4 bytes. Shouldn't it be 5 bytes because an integer is 4 bytes? Why is that 1 byte being neglected?

Same reason as with the vtable example -- any non-zero-sized object can have a unique address, and so the only time you need to add the single byte is for an object that would otherwise be zero-sized. An object with an integer will not be zero-sized in any case, so there's no need to add an extra byte.

Related