Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C++ (http://www.go4expert.com/articles/cpp-tutorials/)
-   -   Size of a C++ class object (http://www.go4expert.com/articles/size-cpp-class-object-t16676/)

Mridula 26Mar2009 14:57

Size of a C++ class object
 

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 6Apr2009 15:02

Re: Size of a C++ class object
 
Article of the month competition nomination started here

shabbir 17Apr2009 14:15

Re: Size of a C++ class object
 
Vote for this article as Article of the month

drdebcol 14Jun2009 16:54

Re: Size of a C++ class object
 
I have never seen this "public virtual" declaration !
What is it basically ?
BTW Great article !

xpi0t0s 14Jun2009 18:58

Re: Size of a C++ class object
 
Quote:

Originally Posted by drdebcol (Post 49547)
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 14Jun2009 21:55

Re: Size of a C++ class object
 
Quote:

Originally Posted by xpi0t0s (Post 49549)
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 17Jun2009 18:25

Re: Size of a C++ class object
 
Thanks to drdebcol.
Many thanks to xpi0t0s for answering drdebcol's question.

mridula.

Karpov2007 18Jun2009 18:55

Re: Size of a C++ class object
 
Relevant blog post:
Viva64 for optimizing data structures

and article:

Optimization of 64-bit programs (see Memory usage decrease)


All times are GMT +5.5. The time now is 10:39.