Estimate the Size of a Class/Object

in

There are many factors that decide the Size of a/an Class/Object in C++. And they are:

  1. . Size of All non-static Data Member
  2. . Order of data members
  3. . Byte Alignment or Byte padding
  4. . Size of its immediate Base class.
  5. . Any existence of virtual function(s) (Dynamic polymorphism using virtual).
  6. . Compiler being used
  7. . Mode of inheritance. (virtual inheritance)

1. Size of All non-static Data Member

Only non-static data member will be counted for calculating sizeof class/object.

class A {
private:
        float iMem1;
        const int iMem2;
        static int iMem3;
        char iMem4;
};

For this class A, size will be, sizeof (float iMem1+ int iMem2+char iMem3); Static members are really not part of Class. They wont be included in Class/Object layout.

2. Order of data members

Order in which one specify data member also alters size of the class.

class C {
        char c;
        int int1;
        int int2;
        int i;
        long l;
        short s;
};

Size of this class is, 24 bytes. Because, even though char c will consume only 1 byte, 4 bytes will be allocated for it and remaining 3 bytes will be waste (holes). It's because, next member is int, which takes 4 bytes. If we don't go to next 4th byte for storing this integer member, memory access/modify cycle for this integer will be 2 read cycle. So compiler will defaultly does this for us, unless and until we specify some Byte padding/packing.

If I re-write the above class in different order, keeping all my data members like below:

class C {
 int int1;
 int int2;
 int i;
 long l;
 short s;
 char c;
};

Now the Size of this class is, 20 bytes.

Its because, in this case, its using one of 2 the extra hole in final 4 bytes.

3. Byte Alignment or Byte padding

As mentioned above, if we specify 1 byte alignment, size of the class above (class C) will be 19 in both cases.

4. Size of its immediate Base class

Size of a class also includes size of its immediate Base. Lets take on example:

Class B {
...
        int iMem1;
        int iMem2;
}

Class D: public B {
...
        int iMem;
}

In this case, sizeof(D) is sizeof D's also includes size of B also. So, it will be 12 bytes.

5. Any existence of virtual function(s)

Existence of virtual function(s) will add 4 bytes of virtual table pointer in the class, which will be added to size of class. Again, in this case, if the base class of the class already has virtual function(s) either directly or through its Base class, then this additional virtual function wont add anything to the size of the class.

Virtual Table Pointer will be common across the class Hierarchy. That is

class Base {
public:
...
        virtual void SomeFunction(...);
private:
        int iAMem
};

class Derived : public Base {
...
        virtual void SomeOtherFunction(...);
private:
        int iBMem
};

In the example above, sizeof(Base) will be 8 bytes, that is sizeof(int iAMem) + sizeof(vptr). And sizeof(Derived) will be 12 bytes, that is sizeof(int iBMem) + sizeof(Derived). Notice that, existence of virtual function in Class Derived wont add anything more. Now Derived will set the vptr to its own Virtual Function Table.

6. Compiler being used

In some scenario, it's compiler specific. Lets take one example:

class BaseClass {
        int a;
        char c;
};

class DerivedClass : public BaseClass {
        char d;
        int i;
};

In case of Microsoft C++ compiler, size of DerivedClass is, 16 bytes In case of gcc (either c++ or g++), size of DerivedClass is, 12 bytes

The reason for sizeof(DerivedClass) being 16 bytes in MC++ is, it starts each class with a 4 byte aligned address so that accessing the member of that class will be easy (Again, Memory read/write cycle)

7. Mode of inheritance. ( virtual inheritance)

In C++, sometimes we have to use virtual inheritance for some reasons. (One classic example is, implementation of final class in C++) When we do virtual inheritance, there will be one overhead of 4 bytes of virtual base class pointer in that class.

class ABase{
        int iMem;
};

class BBase : public virtual ABase {
        int iMem;
};

class CBase : public virtual ABase {
        int iMem;
};

class ABCDerived : public BBase, public CBase {
        int iMem;
};

And if you check the size of these classes, it will be:
-  Size of ABase : 4
-  Size of BBase : 12
-  Size of CBase : 12
-  Size of ABCDerived : 24

Its because, as BBase and CBase are deriving ABase virtually, it will also have an virtual base pointer. So, 4 bytes will be added to the size of the class (BBase and CBase). That is sizeof ABase + size of int + sizeof Virtual Base pointer.

Size of ABCDerived will be 24 (not 28 = sizeof (BBase + CBase + int member)) because; it will maintain only one Virtual Base pointer (Same way of maintaining virtual table pointer).


> Estimate the Size of a Class/Object

I would like to add that the empty base class optimization (EBCO) may reduce the size in some cases.

A tip: because sizeof( ClassName ) is a compile-time constant, you can find out the value by compiling. You can do like this:

switch(1)
{
case 1:
case 2:
case 3:
case 4:
... etc.

case sizeof( ClassName ):

}

When you compile, you'll get an error like "error C2196: case value '20' already used". In that case, the sizeof( ClassName ) is 20 bytes.

Or alternatively, you can write a C++ template to do the same without a long switch statement.

> Estimate the Size of a Class/Object

Hi Girish, 1. I think in the first bullet iMem3 should be replaced by iMem4, becauuse iMem4 is static member. 2. If you can add one more bullet regarding the size of empty class

> Estimate the Size of a Class/Object

>>Hi Girish, 1. I think in the first bullet iMem3 should be replaced by iMem4, becauuse iMem4 is static member. Yeah, you are right, another mistake there, The whole sentense should be replaced by

Defination of Class remains same, there is some correction in the below line:

For this class A, size will be, sizeof (float iMem1+ int iMem2+char iMem4); Static members are really not part of Class. They wont be included in Class/Object layout.

>>2. If you can add one more bullet regarding the size of empty class Yeah, can add more on size of Empty class.

Size of Empty class will be a byte (minimum memory that can be accessed). Its because, suppose we have a class with out any members in that, then theoratically, its as good as class with size 0. But it does not make any sense practically.

class EmptyClass

;

When someone instantiates an object of that class, if the size is 0, then its as good as refering to something which is not existing! Lets say, I have two objects of EmptyClass, obj1, obj2. What should happen when I do, obj1 = obj2; ? We dont have any existance for these objects !! So, compiler will keep 1 byte of memory for Empty class

Regards Girish