Consider the following inheritance:
class Base {
protected:
Base() { }
public:
double Multiply(double x);
};
class Derived : public Base {
double _value;
public:
Derived(double init) : _value(init) { }
double Multiply(double x) { return x*_value; }
};
This code piece is to be used in templated codebase. Polymorphism is not an option because it adds VTable pointer thus doubles the memory consumption.
However, I suspect that because of C++ requirement for objects to have size at least 1 byte, the size of Derived
would become 9 bytes and, consequently, because of padding/alignment it will further become 16 bytes.
So is there a way in C++ to keep the size of Derived
equal to the size of double
(usually 8 bytes) ?
What does the standard say about the size of Derived
?
Particularly, how does MSVC++ behave in this case?
This is called Empty base optimization, it is defined in standard as following:
1.8 The C ++ object model [intro.object]
7 Unless it is a bit-field (9.2.4), a most derived object shall have a nonzero size and shall occupy one or more bytes of storage. Base class subobjects may have zero size. An object of trivially copyable or standard-layout type (3.9) shall occupy contiguous bytes of storage.
8 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 a and b with overlapping lifetimes that are not bit-fields may have the same address if one is nested within the other, or if at least one is a base class subobject of zero size and they are of different types; otherwise, they have distinct addresses.
In your example inheriting Base
class does not affect the size of the Derived
class. However MSVC++ performs such optimization only for a first empty base class so inheriting from addition empty base classes will lead to growth of Derived
class size. I believe this has been a point of critisim towards MSVC++ for a long time, as many other compilers don't have this issue. This can be really troublesome if you have a lot of small auxiliary classes. As a workaround a deriving template base class could be used to convert multiple inheritance into a chain of single inheritance:
class Base1
{};
template< typename TBase > class Base2: public TBase
{};
template< typename TBase > class Base3: public TBase
{};
class Derived: public Base3< Base2< Base1 > >
{};
MS Connect bug page. It looks like they aren't aiming to fix it after all.