Empty derived optimization

假如想象 提交于 2019-12-05 10:44:35

The standard does not contain an "empty base class" case per se. Rather, it says (cf. 1.8):

[A] most derived object shall have a non-zero size and shall occupy one or more bytes of storage. Base class subobjects may have zero size.

And:

Unless an object is [...] a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Two objects [...] 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.

And (Clause 9):

Complete objects and member subobjects of class type shall have nonzero size. Footnote: Base class subobjects are not so constrained.

This never says that only empty bases are amenable to any kind of layout change and leaves ample room for "squeezing" the layout: for example:

struct A {}; struct B : A { int x; };             // "equivalent" to { int }

struct X { int a; }; struct Y : X {};             // "equivalent" to { int }

Consider B b; and Y y;. it is possible that the address of b, that of the A-subobject of b (i.e. &static_cast<A&>(b)) and that of b.x are the same, and similarly that the address of y, the X-suboject of y, and the address of y.a are the same.

The only thing that does not work is this:

struct S {}; struct T { S s; };                   // "equivalent" to { char }

By "equivalent" I mean the most sensible, space-saving implementation.

A more interesting case is the following:

struct Foo { int x; char a; };                    // { int, char, char[3] }

struct Bar : Foo { short q; };                    // { int, char, char, short }

This example assumes sizeof(int) == 4 and sizeof(short) == 2. We have sizeof(Foo) == 8 for alignment reasons, but sizeof(Bar) is also 8 despite having more data members.


Another relevant part of the standard is 9.2/13:

Nonstatic data members of a (non-union) class with the same access control (Clause 11) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified (11). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).

Finally, 9.2/10 says that standard-layout classes have no padding at the beginning, so that their address equals the address of their "initial member". Since standard-layout requires that all bases either be empty, or that the most-derived class itself have no data members, this means that standard-layout classes must employ a kind of "empty base" optimization, and the initial part of the layout of my B and Y above is actually mandatory.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!