Is C++ allowed to increase the derived class size if there're no new member variables compared to the base class?

C++InheritanceSizeofLanguage Lawyer

C++ Problem Overview


Suppose I have a base class with some member variables and no virtual functions:

class Base {
   int member;
};

and a derived class that derives in a non-virtual way from Base and has no new member variables an again no virtual functions:

class Derived : Base {
};

Obviously sizeof(Derived) can't be smaller than sizeof(Base).

Is sizeof(Derived) required to be equal to sizeof(Base)?

C++ Solutions


Solution 1 - C++

From 5.3.2 [expr.sizeof]

>When applied to a class, the result [of sizeof] is the number of bytes in an object of that class including any padding required for placing objects of that type in an array. The size of a most derived class shall be greater than zero (1.8).

From 1.8 [intro.object]

>Unless it is a bit-field (9.6), a most derived object shall have a non-zero size and shall occupy one or more bytes of storage. Base class sub-objects may have zero size. An object of POD type (3.9) shall occupy contiguous bytes of storage.

and a note:

>The actual size of a base class subobject may be less than the result of applying sizeof to the subobject, due to virtual base classes and less strict padding requirements on base class subobjects.

Put these together and I think what it's telling you is that you have no guarantees whatsoever as to what sizeof might tell you, other than the result will be greater than zero. In fact, it doesn't even seem to guarantee that sizeof(Derived) >= sizeof(Base)!

Solution 2 - C++

There is no such requirement.

The only relevant part of the language I can think of is that every object, whether complete or not, and whether most-derived or not, has an identity, which is given by the pair of its address and its type. Cf. C++11 1.8/6:

> 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.

So both the most-derived object and the base subobject of your example must have distinct identities.

It would certainly make sense for a compiler to give both Base and Derived a size of 1, but this is not mandatory. It would be acceptable if the Base had size 1729 and Derived had size 2875.

Solution 3 - C++

Interesting question. I have an example where a derived class with an extra field is the same size as an empty base class. (This should be a comment but is much too large; please accept one of the other answers, although upvotes are welcome if it's interesting.)

Consider this trivial C++ program:

class A {};

class B : public A {
	int m_iInteger;
};

int _tmain(int argc, _TCHAR* argv[])
{
	printf("A: %d\r\n", sizeof(A));
	printf("B: %d\r\n", sizeof(B));
	printf("int: %d\r\n", sizeof(int));

	return 0;
}

What would you expect the output to be, if sizeof(int) is 4? Perhaps something like:

A: 0
B: 4
int: 4

?

My compiler - Embarcadero C++ Builder 2010 - gives the output:

A: 8
B: 8
int: 4

In other words, adding an extra field in the derived class does not make the derived class bigger.

There is some insight into why with the help file topic on the compatibility option Zero-length empty base class.

> Usually the size of a class is at least one byte, even if the class > does not define any data members. When you set this option, the > compiler ignores this unused byte for the memory layout and the total > size of any derived classes; empty base classes do not consume space > in derived classes. Default = False

It appears that the size of a class with default compiler settings for this compiler is 8 bytes, not one, and in fact changing this setting for this code example has no effect.

You may also find this article on base class sizes and the above optimization interesting. It discusses why classes must have a size of at least one byte, what the optimization does, and delves into representation of member functions etc too:

> Indeed, the standard requires that the size of an object shall never > be zero; it also requires that in a derived object data members of the > base class(es) shall appear before user-declared data members of the > derived class. However, a base class subobject isn’t considered a > complete object. Therefore, it’s possible to remove the base class > subobject from the derived object without violating the rules. In > other words, in the object t, the offset of S and x may overlap...

Please read the article for the full context of that quote.

Solution 4 - C++

class Base {
 // int member;            I have just created an empty base class.
};

class Derived : Base {
};

Now gcc compiler would give "size>0" for the both the objects created by Base and Derived classes. gcc compiler just provides the presence of address for the objects to the user.

  Note:Derived class would contain base class members, so obviously we can think of 
  sizeof(derived class) greater then sizeof(base class). But this depends on the compiler 
  if it allocates some extra space while defining the derived class. 

My present gcc compiler showed the sizeof objects of both Base and Derived to be same.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsharptoothView Question on Stackoverflow
Solution 1 - C++Tristan BrindleView Answer on Stackoverflow
Solution 2 - C++Kerrek SBView Answer on Stackoverflow
Solution 3 - C++DavidView Answer on Stackoverflow
Solution 4 - C++Santosh SahuView Answer on Stackoverflow