1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Size of a C++ class object

Discussion in 'C++' started by Mridula, Mar 26, 2009.

  1. Mridula

    Mridula New Member

    Joined:
    Mar 5, 2008
    Messages:
    316
    Likes Received:
    19
    Trophy Points:
    0
    Occupation:
    S/w proffessional
    Location:
    Bangalore

    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:
    #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:
    #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:
    #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:
    #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:
    #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:
    #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:
    #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
     
  2. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,293
    Likes Received:
    365
    Trophy Points:
    83
    Article of the month competition nomination started here
     
  3. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,293
    Likes Received:
    365
    Trophy Points:
    83
  4. drdebcol

    drdebcol New Member

    Joined:
    Jun 14, 2009
    Messages:
    4
    Likes Received:
    0
    Trophy Points:
    0
    Occupation:
    Admin of Bank Database
    Location:
    Kernel Memory
    Home Page:
    I have never seen this "public virtual" declaration !
    What is it basically ?
    BTW Great article !
     
  5. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,012
    Likes Received:
    203
    Trophy Points:
    0
    Occupation:
    Senior Support Engineer
    Location:
    England
    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).
     
  6. drdebcol

    drdebcol New Member

    Joined:
    Jun 14, 2009
    Messages:
    4
    Likes Received:
    0
    Trophy Points:
    0
    Occupation:
    Admin of Bank Database
    Location:
    Kernel Memory
    Home Page:
    Now i understand, THX !
    C++ has so many options . . .
     
  7. Mridula

    Mridula New Member

    Joined:
    Mar 5, 2008
    Messages:
    316
    Likes Received:
    19
    Trophy Points:
    0
    Occupation:
    S/w proffessional
    Location:
    Bangalore
    Thanks to drdebcol.
    Many thanks to xpi0t0s for answering drdebcol's question.

    mridula.
     
  8. Karpov2007

    Karpov2007 Banned

    Joined:
    Oct 14, 2007
    Messages:
    66
    Likes Received:
    2
    Trophy Points:
    0
    Occupation:
    scientific adviser of OOO "Program Verification Sy
    Location:
    Russia, Tula
    Home Page:

Share This Page