Size of a C++ class object

Mridula's Avatar author of Size of a C++ class object
This is an article on Size of a C++ class object in C++.

Introduction



This article talks about size of a class with all possible scenarios like having simple data (with and without structure padding), virtual functions, Replicated and Shared Multiple Inheritance etc.

Background



Size of a class object is nothing but it's non-static member data + if it has any virtual functions, then it's _vptr size + it's inherited data, if it is inherited from some class.

Static data is a shared data (class data) and will not be consdered as part of the size of a object. Also, the size of class object differs when it has derived from a single class or multiple classes.

Lets see see some scenarios as below:

Size of a simple class object (without having structure padding)

Code: Cpp
#include<iostream.h>

class Base{
  char a;
  int b;
  char c;
  int d;
  static int e;
};

int main()
{
  Base b;

  //Only non-static data
  cout<<"SIZE OF CLASS BASE (without padding) = "<<sizeof(b)<<endl;
  return (0);
}

output:

SIZE OF CLASS BASE (without padding) = 16

Here we can see, that data is declared randomly, without considering structure padding. For padding, we need to make sure, larger size data must be declared initially and then declare the small size data.

Like here in this above example, int is a large data - holds 4 bytes and char is small size holds 1 byte.

And so,

char a = 4 bytes
int b = 4 bytes,
char c = 4 bytes
int d = 4 bytes and occupies 16 bytes.

Size of a simple class object (with structure padding)

Code: Cpp
#include<iostream.h>

class Base{
  int b;
  int d;
  char a;
  char c;
  static int e;
};

int main()
{
  Base b;

  //Only non-static data
  cout<<"SIZE OF CLASS BASE (without padding) = "<<sizeof(b)<<endl;
  return (0);
}

output:

SIZE OF CLASS BASE (without padding) = 12

Here in the class, data is declared considering the structure padding. So for the above
example, all integers are declared initially and then declared the char data.

And so,

int b = 4 bytes
int d = 4 bytes
char a = 2 bytes
char c = 2 bytes and so occupies only 12 bytes.

Size of a simple class object with a Virtual function

Code: Cpp
#include<iostream.h>

class Base
{
  int a;

  public:
    virtual void func1(void){};
};

int main()
{
  Base b;

  //Only non-static data
  cout<<"SIZE OF CLASS BASE (with Virtual Function) = "<<sizeof(b)<<endl;
  return (0);
}

output:

SIZE OF CLASS BASE (with Virtual Function) = 8

Here compiler secretly inserts a _vptr (nothing but a pointer to virtual table) and so this _vptr size is also considered while calculating the size of a class object here. Also, here the size remains the same even if we have more than one virtual functions.

Here for the example:

int a = 4 bytes
_vptr = 4 bytes and so occupies 8 bytes

Size of a class object with Single Inheritance

Code: Cpp
#include<iostream.h>

class Base
{
  int a;

  public:
    virtual void func1(void){};
};

class Derive: public Base
{
   public:
    virtual void func2(void){};
};

int main()
{
  Derive d;

  //Only non-static data
  cout<<"SIZE OF CLASS BASE (with Single Inheritance) = "<<sizeof(d)<<endl;
  return (0);
}

output:

SIZE OF CLASS BASE (with Single Inheritance) = 8

Here _vptr is derived to the Derive class from it's Base and so only one _vptr will be
there in single inheritance.

Here for the example:

int a = 4 bytes (inherited again)
_vptr = 4 bytes and so occupies 8 bytes

Size of a class with Multiple Inheritance

Code: Cpp
#include<iostream.h>

class Base1{
  public:
    virtual void func1(void){};
};

class Base2 {
  public:
    virtual void func2(void){};
};

class Derive: public Base1, Base2{
  public:
    virtual void func3(void){};
};

int main()
{
  Derive d;

  //Only non-static data
  cout<<"SIZE OF CLASS DERIVE (with MI) = "<<sizeof(d)<<endl;
  return (0);
}

output:

SIZE OF CLASS DERIVE (with MI) = 8

Here class Derive is derived from Base1 and Base2 classes and these classes have virtual functions with their respective _vptrs in them. And so the size of a derived class in MI, is it's base classes _vptrs size + it's data (including inherited ones).

Here for the example:

_vptr of Base1 class = 4 bytes
_vptr of Base2 class = 4 bytes and so occupies 8 bytes


Size of a class with Replicated Multiple Inheritance

Code: Cpp
#include<iostream.h>

class Base1{
  public:
    int a;
};

class Base2 : public Base1{
  public:
    virtual void func2(void){};
};

class Base3 : public Base1{
  public:
    virtual void func3(void){};
};

class Derive: public Base2, Base3{
  public:
    virtual void func3(void){};
};

int main()
{
  Derive d;

  //Only non-static data
  cout<<"SIZE OF CLASS DERIVE (with Replicated MI) = "<<sizeof(d)<<endl;
  return (0);
}

output:

SIZE OF CLASS DERIVE (with Replicated MI) = 16

Here class Derive is derived from classes Base2 and Base3 which are in turn derived from class Base1 normally. So, Derive object will have the data int a duplicated from class Base2 and class Base3 as well, apart from having _vptr from it's Base classes.

Here for the example:

_vptr of Base2 class = 4 bytes
int a from Base2 class = 4 bytes
_vptr of Base3 class = 4 bytes
int a from Base3 class = 4 bytes and so occupies 16 bytes


Size of a class with Shared Multiple Inheritance

Code: Cpp
#include<iostream.h>

class Base1{
  public:
    int a;
};

class Base2 : public virtual Base1{
  public:
    virtual void func2(void){};
};

class Base3 : public virtual Base1{
  public:
    virtual void func3(void){};
};

class Derive: public Base2, Base3{
  public:
    virtual void func3(void){};
};

int main()
{
  Derive d;

  //Only non-static data
  cout<<"SIZE OF CLASS DERIVE (with Virtual Base) = "<<sizeof(d)<<endl;
  return (0);
}

output:

SIZE OF CLASS DERIVE (with Virtual Base) = 12

Here since Base2 and Base3 classes are derived from Virtual Base class, so Derive class, which is derived from these classes, will have only one set of data from the foremost Base class i.e. Base1 class here, which will be part of this Derive class object and is shared by Base2 and Base3 classes.

Here for the example:

_vptr of Base2 class = 4 bytes
_vptr of Base3 class = 4 bytes
int a from Base1 class = 4 bytes and so occupies only 12 bytes

References



Here are the References on detail about _vptr and virtual table in Single and Simple Multiple Inheritance cases

How Virtual Table and _vptr works
Virtual Table and _vptr in Multiple Inheritance
shabbir's Avatar, Join Date: Jul 2004
Go4Expert Founder
Article of the month competition nomination started here
shabbir's Avatar, Join Date: Jul 2004
Go4Expert Founder
Vote for this article as Article of the month
drdebcol's Avatar, Join Date: Jun 2009
Newbie Member
I have never seen this "public virtual" declaration !
What is it basically ?
BTW Great article !
xpi0t0s's Avatar, Join Date: Aug 2004
Mentor
Quote:
Originally Posted by drdebcol View Post
I have never seen this "public virtual" declaration !
What is it basically ?
That's what the article is about. The 4th code example shows you what public inheritance is, and there are two other types of inheritance: private and protected.

The 5th code example shows you what multiple inheritance is and why you need "virtual" in there if you have multiple inheritance from classes that themselves share the same base class. If you have Base, and Derived1 and Derived2 derived from Base, and Derived3 derived from Derived1 and Derived2, then Derived3 will contain 2 Base's (Derived1's and Derived2's).
drdebcol's Avatar, Join Date: Jun 2009
Newbie Member
Quote:
Originally Posted by xpi0t0s View Post
That's what the article is about. The 4th code example shows you what public inheritance is, and there are two other types of inheritance: private and protected.

The 5th code example shows you what multiple inheritance is and why you need "virtual" in there if you have multiple inheritance from classes that themselves share the same base class. If you have Base, and Derived1 and Derived2 derived from Base, and Derived3 derived from Derived1 and Derived2, then Derived3 will contain 2 Base's (Derived1's and Derived2's).
Now i understand, THX !
C++ has so many options . . .
Mridula's Avatar, Join Date: Mar 2008
Pro contributor
Thanks to drdebcol.
Many thanks to xpi0t0s for answering drdebcol's question.

mridula.