Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is sizeof(BaseClass) == sizeof(DerivedClass) although I add a member

Tags:

c++

oop

sizeof

From the code below sizeof(Base) == 24 and sizeof(Derived) == 24.

Why are their sizes equal?

In Base class we have 3 members and in Derived class we have another member.

class Base { private:     double d; protected:     long l; public:     int i; };  class Derived : public Base { private:     float f; }; 
like image 421
Axazeano Avatar asked Jan 19 '14 18:01

Axazeano


2 Answers

It just so happened that your class Base has 8 byte alignment requirement, but its last member has size 4. This leads to an empty padding area added at the end of Base's memory layout. That extra padding plays its role when you instantiate objects of class Base by themselves, as so called most-derived objects.

Base b; // <- a most-derived object Base a[10]; // <- an array of most-derived objects 

However, when you "embed" Base as base class into class Derived, there's no need for that extra padding at the end of the embedded Base subobject.

Derived d; // <- object `d` contains an embedded sub-object of type `Base` 

A smart compiler will attempt to reuse that area by placing the extra field of class Derived into the layout area used for padding in Base. In your case the extra field Derived::f incidentally has the same size of 4 bytes, i.e. it fits in there perfectly. The end result is that the total size of the class does not increase.

A very similar (in nature) effect is so called "empty base optimization". In C++ sizeof for any type is guaranteed to be greater than 0, which means that sizeof of an empty class is always greater than zero. However, when you derive some other class from an empty base class, you might observe that the base class contributes exactly 0 bytes to the derived class's size. For example

struct A {}; struct B {}; struct C {}; struct D {};  struct F : A, B, C, D {   int i; }  int main() {   std::cout << sizeof(A) << std::endl << sizeof(B) << std::endl <<                 sizeof(C) << std::endl << sizeof(D) << std::endl;   std::cout << sizeof(F) << std::endl; } 

Even though sizeof of each base class is greater than zero, sizeof(F) will typically still evaluate to sizeof(int), as if base class subobjects do not exist at all.

In other words, as such examples show, base class subobjects follow noticeably more relaxed rules with regard to their memory layout than most-derived objects. These relaxed rules might easily lead to situations when sizeof of base class will only partially contribute to sizeof of derived class.

like image 127
AnT Avatar answered Sep 20 '22 15:09

AnT


Because you have sizeof(double) == sizeof(long) == 8 and it often means alignof(double) is equal to 8 too. It means that Base must be size aligned on an 8 bytes boundary in case it is store in an array, and it generates a 4 bytes padding at the end, Derived removes that to put f instead.

like image 36
galop1n Avatar answered Sep 18 '22 15:09

galop1n