Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should an empty base class affect the layout of the derived class?

The C++ standard (quoting from draft n3242) says the following about subobjects [intro.object]:

Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Two distinct objects that are neither bit-fields nor base class subobjects of zero size shall have distinct addresses.

Now, given the following snippet:

struct empty { };
struct member: empty { };
struct derived: empty { member m; };

int main(void)
{
    printf("%d", sizeof(derived));
    return 0;
}

gcc I believe prints out 2, and Visual C++ 2010 prints out 1. I suspect gcc is taking the standard to mean you can't alias the storage of types if they represent different objects. And I bet MSVC is taking the standard to mean if one subobject is zero sized, you can do whatever you want.

Is this unspecified behavior?

like image 261
MSN Avatar asked Oct 13 '11 20:10

MSN


3 Answers

Expanding on my earlier comment:

An object is identified by its address. If you compare the addresses (like pointers) of two objects of the same type and they compare equal, the pointers are considerd to point to the same object.

Objects of different types cannot be compared directly this way, so they are allowed to have the same address. One example is a struct and its first member. They cannot be of the same type. Neither can a base class and a derived class, so they could possibly have the same address if the base class is empty.

However, a base class and the first member of the derived class can be of the same type. This is not a problem unless the base class is also empty and the compiler tries the empty base class optimization. In that case we could have pointers to two different objects of the same type compare equal, and therefore believe that they were the same object.

So, if the members have different types (empty and char) they can have the same address. If they are of the same type they cannot, because that would break tests for object identity like if (this != &that), sometimes used to test for things like self assignment.

By the way, Microsoft agrees that this is a bug in their compiler but have other, more urgent, things to fix first.

like image 176
Bo Persson Avatar answered Oct 04 '22 04:10

Bo Persson


This is implementation-dependent.

The standard explicitly allows the Empty Base Optimization, but does not require it. In fact, the standard doesn't require much of anything about the layout of classes in memory, only that certain classes will be layout-compatible with each other (but not what the common layout is). Order of members is also specified (when there is no intervening accessibility specifier), but padding, headers, footers, and all manner of weirder stuff is allowed.

like image 40
Ben Voigt Avatar answered Oct 04 '22 03:10

Ben Voigt


In the final version of the C++11 standard, that paragraph was revised to read:

Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Two objects that are not bit-fields may have the same address if one is a subobject of the other or if at least one is a base class subobject of zero size and they are of different types; otherwise, they shall have distinct addresses.

Although I am not sure I understand what this has to do with the sizes of the objects.

like image 29
Nemo Avatar answered Oct 04 '22 03:10

Nemo