Wednesday, November 13, 2013

Sizeof Class / Data Members

Sizeof Class / Data Members

There are many factors that decide the size of an object of a class in C++. These factors are:
  1. Size of all non-static data members
  2. Order of data members
  3. Byte alignment or byte padding
  4. Size of its immediate base class
  5. The existence of virtual function(s) (Dynamic polymorphism using virtual functions).
  6. Compiler being used Mode of inheritance (virtual inheritance)
1. Sizeof Class with No data members:

Generally, for class without any data members, the size of the object of the class would be equals to 1.

i.e Have a look at the below example

Class Student
{
        //Function Definition
};

int main()
{
       Student S1;
       cout<<"The size of Empty class is "<<sizeof(S1);
       return 0;
}

The o/p would be 1. sizeof can never return 0. Logically, structure/class with 0 bytes does not exists. Hence minimum memory is allocated for a character data type which is one byte. That will be provided for an empty class.

2. Sizeof Class with data members:

Generally, for class with any data members, the size of the object of the class would be equals to amount of bytes the data members occupy.

i.e Have a look at the below example

Class Student
{
        private:
            int rollno;
        
        public:
            int getrollno()
            {
                 return rollno;
            }
            void setrollno(int rlno)
            {
                 rollno=rlno;
            }
};

int main()
{
       Student S1;
       cout<<"The size of this class is "<<sizeof(S1);
       return 0;
}

The output of the code would result to 4. i.e sizeof(int)= 4 bytes for the rollno.

3. Sizeof Class with data members without padding:

Generally, for class with any data members, the size of the object of the class would be equals to amount of bytes the data members occupy.

i.e Have a look at the below example

Class Student
{
        private:
            char section; 
            int rollno;
            char grade;
        
        public:
            int getrollno()
            {
                 return rollno;
            }
            void setrollno(int rlno)
            {
                 rollno=rlno;
            }
};

int main()
{
       Student S1;
       cout<<"The size of this class is "<<sizeof(S1);
       return 0;
}

If you compute the sizeof class as 6, (int-4, char-1) then you are absolutely wrong. Generally the order of data members defined place a vital role in allocating memory.

In our example, first character is declared. Although character takes only one byte, it allocates 4 bytes of block of memory in which only the first byte is used, the remaining three bytes are used with filler bits.

For integer, it will allocate 4 bytes. And again for the character 'grade', it allocates 4 bytes of memory.
The output of the above will result to 12.

Hence padding concept can be used to avoid this kind of high memory usage.

4. Sizeof Class with data members with padding:

Padding - Data members with higher memory usage are declared first followed by the lower order.

Generally, for class with any data members, the size of the object of the class would be equals to amount of bytes the data members occupy.

i.e Have a look at the below example

Class Student
{
        private:
            int rollno;
            char section;  
            char grade;
        
        public:
            int getrollno()
            {
                 return rollno;
            }
            void setrollno(int rlno)
            {
                 rollno=rlno;
            }
};

int main()
{
       Student S1;
       cout<<"The size of this class is "<<sizeof(S1);
       return 0;
}

Now integer will allocate 4 bytes, and the remaining two characters fills another two bytes.
The output would be 8.

Hence padding concept can be used to avoid this kind of high memory usage.


5. Sizeof Class with one virtual member function:

For the class with virtual functions, it allocates additional 4 bytes of memory for the pointer to virtual table.

Class Student
{
        private:
            int rollno;
        
        public:
            virtual void display()
            {
            }
};

int main()
{
       Student S1;
       cout<<"The size of this class is "<<sizeof(S1);
       return 0;
}

The output would be equals to 8.



6. Sizeof Class with two or more virtual member functions:

For the class with virtual functions, it allocates additional 4 bytes of memory for the pointer to virtual table.
Any number of virtual functions are available, the pointer remains only one.

Class Student
{
        private:
            int rollno;
        
        public:
            virtual void display()
            {
            } 

            virtual void treatsignal()
            {
            }
};

int main()
{
       Student S1;
       cout<<"The size of this class is "<<sizeof(S1);
       return 0;
}

The output would still be equals to 8.

7. Sizeof Derived Class:

The size of derived class will occupy space for data members of immediate base class + memory allocation for its own class.

Class Student
{
        public:
            int rollno;
        
        public:
            virtual void display()
            {
            }
};

Class Marks : public Student
{
        private:
            int mark1;
            int mark2;

        public:
            virtual void display()
            {
            }
};

int main()
{
       Marks m;
       cout<<"The size of this class is "<<sizeof(m);
       return 0;
}

The output would be Baseclass member (rollno)(4) + Virtualptr (4) in baseclass + Ownclass members (4 + 4) equals to 16.


8. Sizeof Derived Class inherited twice:

The size of derived class will occupy space for data members of immediate base class + memory allocation for its own class.

class Student
{
       int rollno;
};

class  marks : public Student
{
};

class performance: public marks
{
     char grade;
     char rank;
};

The size will be Baseclass member + own class will be equals to 8.

9. Size of all non-static data members:
Only non-static data members will be counted for calculating sizeof class/object.

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


For an object of class A, the size will be the size of float iMem1 + size of int iMem2 + size of char iMem4. Static members are really not part of the class object. They won't be included in object's layout.

Mode of inheritance (virtual inheritance):

In C++, sometimes we have to use virtual inheritance for some reasons. (One classic example is the implementation of final class in C++.) When we use virtual inheritance, there will be the overhead of 4 bytes for a 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

Because BBase and CBase are derived from ABase virtually, they 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).       

No comments:

Post a Comment