C++ : How can I know the size of Base class SubObj

2019-01-26 20:48发布

.

Here I was discussing Empty Base Optimization, and MSalters made this interesting comment:

No class can ever have sizeof(Class)==0, empty or not. But we're talking specifically over the size of an empty base class subobject. It doesn't need its own vtable, nor a vtable pointer. Assume the common layout of a vtable pointer at offset 0; that would cause the zero-sized base class subobject to share its vtable pointer with the derived class. No problem: those should be identical anyway, that's pretty much the point of virtual functions.

My question specifically is this: compiler may optimize when we use Empty Class as base class, or it may not. How would we determine as to what it actually does?

And in general, how can we know the size of base class subobject? Is the size of Base subobject same irrespective of whether we use it as base or not? Do compilers optimize only with Empty Base Classes?

.

3条回答
甜甜的少女心
2楼-- · 2019-01-26 20:57

Good answers.

By the way, MS VC++ and G++ compilers can dump class layouts for you to study.

With VC++ just run cl.exe /c /d1reportAllClassLayout <source>.cpp

This uses class and vtable layout dump code I wrote in 1990 to test proper layout objects, vtables, vbtables, etc.

To better understand how C++ compilers lay out objects in memory, you might enjoy http://www.openrce.org/articles/files/jangrayhood.pdf and Stan Lippman's book Inside the C++ Object Model.

Happy hacking!

查看更多
干净又极端
3楼-- · 2019-01-26 21:12

The minium size of an object is 1:

class X {};
sizeof(X) >= 1

But a derived class does not need to allocate room for this space if it is not used:

class Y : public X {};
sizeof(Y) >= 1

So even though the class X by itself takes up 1 byte this is not translated to the parent class. So from Y's perspective the class X takes up 0 bytes.

So here we can say that the compiler has optimizes away the base class (though technically it has done nothing. We just need to enforce the rule that no object has zero size).

int main()
{
    std::cout << sizeof(X) << ":" << sizeof(Y) << "\n";
}

Generates the following output:

> ./a.exe
1:1
>

The reason a class must have a size greater than zero is so that the address of every object is unique. If the compiler allowed a class to have zero size then there is a potential easy bug where multiple variables (objects) all had the same memory address (as they all had zero size). The simple rule to get around this potential problem is that all objects must have a non zero size.

Summary:

size_of_type(X) = size_of_type(base) + sum(size_of_type(members)) + padding + (extra stuff like vtable pointer etc);


sizeof(<CLASS>) = min(1, size_of_type(<CLASS>))
查看更多
男人必须洒脱
4楼-- · 2019-01-26 21:19

You can't. The actually size might differ a lot from the sizeof() information when serving as a base.

One other example than EBO is virtual inheritance.

查看更多
登录 后发表回答